/cwxeditor_src/cwx/flag.d
D | 1693 lines | 1451 code | 55 blank | 187 comment | 262 complexity | 08d6acc656f8589a2dce200a27af8a0d MD5 | raw file
Possible License(s): LGPL-2.1
- module cwx.flag;
- import cwx.utils;
- import cwx.xml;
- import cwx.path;
- import cwx.usecounter;
- import cwx.system;
- import std.algorithm;
- import std.array;
- import std.datetime;
- import std.string;
- import std.typecons;
- import std.exception;
- import std.conv;
- private static const {
- string XML_ROOT_FLAGS_AND_STEPS = "FlagsAndSteps";
- string XML_ROOT_FLAG_DIRECTORY = "FlagDirectory";
- string XML_ATT_ROOT_ID = "rootId";
- string XML_ATT_PATH = "path";
- string XML_ATT_ROOT_NAME = "rootName";
- }
- /// ?????????
- public class FlagException : Exception {
- public:
- this (string msg) { mixin(S_TRACE);
- super(msg);
- }
- }
- /// ????????????XML??????
- public string getXML(FlagDir parent, Flag[] flags, Step[] steps) { mixin(S_TRACE);
- auto e = XNode.create(XML_ROOT_FLAGS_AND_STEPS);
- auto _root = parent.root;
- e.newAttr(XML_ATT_PATH, parent.path);
- e.newAttr( XML_ATT_ROOT_ID, _root.id);
- auto fe = e.newElement("Flags");
- foreach (flag; flags) { mixin(S_TRACE);
- assert (flag.parent.root == _root);
- assert (flag.parent == parent);
- flag.toNode(fe);
- }
- auto se = e.newElement("Steps");
- foreach (step; steps) { mixin(S_TRACE);
- assert (step.parent.root == _root);
- assert (step.parent == parent);
- step.toNode(se);
- }
- return e.text;
- }
- /// ???????????????????XML??????
- public string getXML(string rootName, FlagDir dir) { mixin(S_TRACE);
- return toNode(rootName, dir).text;
- }
- /// ditto
- XNode toNode(string rootName, FlagDir dir) { mixin(S_TRACE);
- auto ret = XNode.create(XML_ROOT_FLAG_DIRECTORY);
- toNode(ret, dir);
- auto _root = dir.root;
- ret.newAttr(XML_ATT_ROOT_ID, _root.id);
- if (_root == dir) { mixin(S_TRACE);
- ret.newAttr(XML_ATT_ROOT_NAME, rootName);
- }
- return ret;
- }
- private void toNode(ref XNode ret, FlagDir dir) { mixin(S_TRACE);
- ret.newAttr(XML_ATT_PATH, dir.path);
- auto fe = ret.newElement("Flags");
- foreach (flag; dir.flags) { mixin(S_TRACE);
- flag.toNode(fe);
- }
- auto se = ret.newElement("Steps");
- foreach (step; dir.steps) { mixin(S_TRACE);
- step.toNode(se);
- }
- foreach (subdir; dir.subDirs) { mixin(S_TRACE);
- auto e = ret.newElement(XML_ROOT_FLAG_DIRECTORY);
- toNode(e, subdir);
- }
- }
- /// ????
- public class Flag : CWXPath {
- private:
- string _name;
- string _on;
- string _off;
- bool _onOff;
- FlagDir _parent;
- void delegate() _change = null;
- public:
- /// ???ID??????
- alias toFlagId toID;
- /// ???????????
- this (Flag copyBase) { mixin(S_TRACE);
- _name = copyBase.name;
- _on = copyBase.on;
- _off = copyBase.off;
- _onOff = copyBase.onOff;
- }
- /// ???On/Off???????On/Off?????????????????
- this (string name, string on, string off, bool onOff) { mixin(S_TRACE);
- _on = on;
- _off = off;
- _onOff = onOff;
- _name = FlagDir.validName(name);
- }
- /// flag?????????????
- void copyFrom(Flag flag) { mixin(S_TRACE);
- name = flag.name;
- on = flag.on;
- off = flag.off;
- onOff = flag.onOff;
- }
- /// ??????????????
- @property
- FlagDir parent() { mixin(S_TRACE);
- return _parent;
- }
- /// ditto
- @property
- const
- const(FlagDir) parent() { mixin(S_TRACE);
- return _parent;
- }
- /// ditto
- @property
- private void parent(FlagDir parent) { mixin(S_TRACE);
- assert (!parent || !parent.getFlag(name));
- _parent = parent;
- }
- /// ???????????
- @property
- FlagDir root() { mixin(S_TRACE);
- return _parent.root;
- }
- /// ditto
- @property
- const
- const(FlagDir) root() { mixin(S_TRACE);
- return _parent.root;
- }
- /// ????????????
- @property
- void changeHandler(void delegate() change) { mixin(S_TRACE);
- _change = change;
- }
- /// ???????????????????????
- @property
- const
- string name() { mixin(S_TRACE);
- return _name;
- }
- /// ditto
- @property
- bool name(string name) { mixin(S_TRACE);
- name = FlagDir.validName(name);
- if (!_parent || _parent.canAppend!Flag(name)) { mixin(S_TRACE);
- if (_change && _name != name) _change();
- _name = name;
- return true;
- }
- return false;
- }
- /// On???????
- @property
- const
- string on() { mixin(S_TRACE);
- return _on;
- }
- /// ditto
- @property
- void on(string on) { mixin(S_TRACE);
- if (_change && _on != on) _change();
- _on = on;
- }
- /// Off???????
- @property
- const
- string off() { mixin(S_TRACE);
- return _off;
- }
- /// ditto
- @property
- void off(string off) { mixin(S_TRACE);
- if (_change && _off != off) _change();
- _off = off;
- }
- /// On/Off?????
- @property
- const
- bool onOff() { mixin(S_TRACE);
- return _onOff;
- }
- /// ditto
- @property
- void onOff(bool onOff) { mixin(S_TRACE);
- if (_change && _onOff != onOff) _change();
- _onOff = onOff;
- }
- const
- override int opCmp(Object o) { mixin(S_TRACE);
- return icmp(name, (cast(Flag) o).name);
- }
- /// ??????????????
- @property
- const
- string path() { mixin(S_TRACE);
- return _parent.path ~ _name;
- }
- /// ??????XML????????
- const
- string toXml() { mixin(S_TRACE);
- auto doc = XNode.create(XML_ROOT_FLAG_DIRECTORY);
- toNode(doc);
- return doc.text;
- }
- /// XML???????????????
- static Flag createFromNode(ref XNode fe, in XMLInfo ver) { mixin(S_TRACE);
- string name = null;
- string tv = "TRUE";
- string fv = "FALSE";
- bool def = parseBool(fe.attr("default", true));
- fe.onTag["Name"] = (ref XNode n) {name = FlagDir.basename(n.value);};
- fe.onTag["True"] = (ref XNode n) {tv = n.value;};
- fe.onTag["False"] = (ref XNode n) {fv = n.value;};
- fe.parse();
- if (!name) throw new FlagException("Flag name not found.");
- return new Flag(name, tv, fv, def);
- }
- /// XML???????????????????
- const
- void toNode(ref XNode node) { mixin(S_TRACE);
- auto e = node.newElement("Flag");
- e.newAttr("default", fromBool(_onOff));
- e.newElement("Name", path);
- e.newElement("True", on);
- e.newElement("False", off);
- }
- @property
- override string cwxPath(bool id) { mixin(S_TRACE);
- return cpjoin(_parent, "flag", .cCountUntil!("a is b")(_parent.flags, this), id);
- }
- override CWXPath findCWXPath(string path) { mixin(S_TRACE);
- if (cpempty(path)) return this;
- return null;
- }
- @property
- const
- override const(CWXPath)[] cwxChilds() {return [];}
- @property
- CWXPath cwxParent() {return _parent;}
- }
- /// ?????
- public class Step : CWXPath {
- private:
- string _name;
- string[] _vals;
- uint _select;
- FlagDir _parent;
- void delegate() _change = null;
- public:
- /// ???ID??????
- alias toStepId toID;
- /// ???????????
- this (Step copyBase) { mixin(S_TRACE);
- _name = copyBase.name;
- _vals = copyBase._vals.dup;
- _select = copyBase._select;
- }
- /// ???????????????????????????????????
- this (string name, string[] vals, uint select) { mixin(S_TRACE);
- _vals = vals;
- _select = select;
- _name = FlagDir.validName(name);
- }
- /// step?????????????
- void copyFrom(Step step) { mixin(S_TRACE);
- name = step.name;
- setValues(step.values, step.select);
- }
- /// ???????????????
- @property
- FlagDir parent() { mixin(S_TRACE);
- return _parent;
- }
- /// ditto
- @property
- const
- const(FlagDir) parent() { mixin(S_TRACE);
- return _parent;
- }
- /// ditto
- @property
- private void parent(FlagDir parent) { mixin(S_TRACE);
- assert (!parent || !parent.getStep(name));
- _parent = parent;
- }
- /// ???????????
- @property
- FlagDir root() { mixin(S_TRACE);
- return _parent.root;
- }
- /// ditto
- @property
- const
- const(FlagDir) root() { mixin(S_TRACE);
- return _parent.root;
- }
- /// ????????????
- @property
- void changeHandler(void delegate() change) { mixin(S_TRACE);
- _change = change;
- }
- /// ??????
- @property
- const
- string name() { mixin(S_TRACE);
- return _name;
- }
- /// ditto
- @property
- bool name(string name) { mixin(S_TRACE);
- name = FlagDir.validName(name);
- if (!_parent || _parent.canAppend!Step(name)) { mixin(S_TRACE);
- if (_change && _name != name) _change();
- _name = name;
- return true;
- }
- return false;
- }
- /// ????????????????
- void setValue(uint index, string value) { mixin(S_TRACE);
- if (_change && _vals[index] != value) _change();
- _vals[index] = value;
- }
- /// ??????????????
- const
- string getValue(uint index) { mixin(S_TRACE);
- return _vals[index];
- }
- /// ????????????
- @property
- const
- uint count() { mixin(S_TRACE);
- return _vals.length;
- }
- /// ?????????????
- @property
- const
- uint select() { mixin(S_TRACE);
- return _select;
- }
- /// ditto
- @property
- void select(uint select) { mixin(S_TRACE);
- if (_change && _select != select) _change();
- _select = .min(select, _vals.length - 1);
- }
- /// ??????????????
- @property
- const
- string value() { mixin(S_TRACE);
- return _vals[_select];
- }
- /// ??????????
- @property
- string[] values() { mixin(S_TRACE);
- return _vals;
- }
- @property
- const
- const(string)[] values() { mixin(S_TRACE);
- return _vals;
- }
- /// ?????????????????
- void setValues(string[] vals, int select) { mixin(S_TRACE);
- assert (select < vals.length);
- if (_change && (_vals != vals || _select != select)) _change();
- _vals = vals;
- _select = select;
- }
- const
- override int opCmp(Object o) { mixin(S_TRACE);
- return icmp(name, (cast(Step) o).name);
- }
- /// ??????????
- @property
- const
- string path() { mixin(S_TRACE);
- return _parent.path ~ _name;
- }
- /// ???????XML????????
- const
- string toXml() { mixin(S_TRACE);
- auto doc = XNode.create(XML_ROOT_FLAG_DIRECTORY);
- toNode(doc);
- return doc.text;
- }
- /// XML???????????????
- static Step createFromNode(ref XNode se, in XMLInfo ver) { mixin(S_TRACE);
- string[] vals;
- string name = null;
- int def = se.attr!(int)("default", true);
- se.onTag["Name"] = (ref XNode n) {name = FlagDir.basename(n.value);};
- se.onTag[null] = (ref XNode n) { mixin(S_TRACE);
- if (startsWith(n.name, "Value")) { mixin(S_TRACE);
- auto numStr = n.name[5 .. $];
- if (isNumeric(numStr)) { mixin(S_TRACE);
- int num = to!(int)(numStr);
- if (num < 0) return;
- if (vals.length <= num) vals.length = num + 1;
- vals[num] = n.value;
- }
- }
- };
- se.parse();
- if (!name) throw new FlagException("Step name not found.");
- if (def < 0 || vals.length <= def) { mixin(S_TRACE);
- throw new FlagException("Step default value invalid. Count: " ~ to!(string)(vals.length) ~ ", default: " ~ to!(string)(def));
- }
- return new Step(name, vals, def);
- }
- /// ?????XML????????????????????
- const
- void toNode(ref XNode node) { mixin(S_TRACE);
- auto e = node.newElement("Step");
- e.newAttr("default", _select);
- e.newElement("Name", path);
- for (int i = 0; i < _vals.length; i++) { mixin(S_TRACE);
- e.newElement("Value" ~ to!(string)(i), _vals[i]);
- }
- }
- @property
- override string cwxPath(bool id) { mixin(S_TRACE);
- return cpjoin(_parent, "step", .cCountUntil!("a is b")(_parent.steps, this), id);
- }
- override CWXPath findCWXPath(string path) { mixin(S_TRACE);
- if (cpempty(path)) return this;
- return null;
- }
- @property
- const
- override const(CWXPath)[] cwxChilds() {return [];}
- @property
- CWXPath cwxParent() {return _parent;}
- }
- /// ???/???????????????????????????
- public class FlagDir : CWXPath {
- private:
- string _name = "";
- CWXPath _owner = null;
- FlagDir _parent = null;
- FlagDir[] _subdir;
- Flag[] _flags;
- Step[] _steps;
- string _id;
- int delegate(string, string) _sorter = null;
- void delegate() _change = null;
- public:
- /// ????????
- static immutable string SEPARATOR = "\\";
- /// ditto
- static immutable string SEPARATOR_REGEX = "\\\\";
- /// ????????
- static string join(string parent, string path) { mixin(S_TRACE);
- if (!parent.length) { mixin(S_TRACE);
- return path;
- }
- if (parent.endsWith(SEPARATOR.dup)) { mixin(S_TRACE);
- return parent ~ path;
- }
- return parent ~ SEPARATOR ~ path;
- }
- /// ???????????????
- package this (CWXPath owner) { mixin(S_TRACE);
- _id = format("%08X", &this) ~ "-" ~ to!(string)(Clock.currTime());
- _owner = owner;
- }
- /// ??????????????
- /// Params:
- /// name = ????????
- this (string name) { mixin(S_TRACE);
- _id = format("%08X", &this) ~ "-" ~ to!(string)(Clock.currTime());
- _name = validName(name);
- }
- /// ???????????
- /// ???????????????????
- this (FlagDir copyBase) { mixin(S_TRACE);
- name = copyBase.name;
- foreach (d; copyBase.subDirs) { mixin(S_TRACE);
- add(new FlagDir(d));
- }
- foreach (f; copyBase.flags) { mixin(S_TRACE);
- add(new Flag(f));
- }
- foreach (s; copyBase.steps) { mixin(S_TRACE);
- add(new Step(s));
- }
- }
- @property
- override string cwxPath(bool id) { mixin(S_TRACE);
- if (_owner) { mixin(S_TRACE);
- return cpjoin(_owner, "variable", id);
- } else if (_parent) { mixin(S_TRACE);
- return cpjoin(_parent, "dir", .cCountUntil!("a is b")(_parent.subDirs, this), id);
- }
- return "";
- }
- override CWXPath findCWXPath(string path) { mixin(S_TRACE);
- if (cpempty(path)) return this;
- auto cate = cpcategory(path);
- switch (cate) {
- case "flag": { mixin(S_TRACE);
- auto index = cpindex(path);
- if (index >= flags.length) return null;
- return flags[index].findCWXPath(cpbottom(path));
- }
- case "step": { mixin(S_TRACE);
- auto index = cpindex(path);
- if (index >= steps.length) return null;
- return steps[index].findCWXPath(cpbottom(path));
- }
- case "dir": { mixin(S_TRACE);
- auto index = cpindex(path);
- if (index >= subDirs.length) return null;
- return subDirs[index].findCWXPath(cpbottom(path));
- }
- default: break;
- }
- return null;
- }
- @property
- const
- override const(CWXPath)[] cwxChilds() { mixin(S_TRACE);
- const(CWXPath)[] r;
- foreach (a; _flags) r ~= a;
- foreach (a; _steps) r ~= a;
- foreach (a; _subdir) r ~= a;
- return r;
- }
- @property
- CWXPath cwxParent() {return _owner ? _owner : _parent;}
- /// ?????????????????????????
- /// ????????????????????
- @property
- void sorter(int delegate(string, string) sorter) { mixin(S_TRACE);
- if (parent) throw new Exception("FlagDir sorter");
- sorterImpl(sorter);
- }
- @property
- private void sorterImpl(int delegate(string, string) sorter) { mixin(S_TRACE);
- _sorter = sorter;
- foreach (sub; subDirs) { mixin(S_TRACE);
- sub.sorterImpl(sorter);
- }
- }
- /// ????????
- @property
- FlagDir parent() { mixin(S_TRACE);
- return _parent;
- }
- /// ditto
- @property
- const
- const(FlagDir) parent() { mixin(S_TRACE);
- return _parent;
- }
- /// ditto
- @property
- private void parent(FlagDir parent) { mixin(S_TRACE);
- assert (!parent || !parent.getSubDir(name));
- _parent = parent;
- }
- /// ????????????
- @property
- void changeHandler(void delegate() change) { mixin(S_TRACE);
- foreach (f; _flags) { mixin(S_TRACE);
- f.changeHandler = change;
- }
- foreach (s; _steps) { mixin(S_TRACE);
- s.changeHandler = change;
- }
- foreach (s; _subdir) { mixin(S_TRACE);
- s.changeHandler = change;
- }
- _change = change;
- }
- /// ???????????
- @property
- FlagDir root() { mixin(S_TRACE);
- auto dir = this;
- while (dir.parent !is null) { mixin(S_TRACE);
- dir = dir.parent;
- }
- return dir;
- }
- /// ditto
- @property
- const
- const(FlagDir) root() { mixin(S_TRACE);
- Rebindable!(const(FlagDir)) dir = this;
- while (dir.parent !is null) { mixin(S_TRACE);
- dir = dir.parent;
- }
- return dir;
- }
- /// ????????ID?????&???????????
- @property
- const
- string id() { mixin(S_TRACE);
- return _id;
- }
- /// ????????
- @property
- const
- string name() { mixin(S_TRACE);
- return _name;
- }
- /// ditto
- @property
- bool name(string name) { mixin(S_TRACE);
- name = FlagDir.validName(name);
- if (!_parent || _parent.canAppendSub(name)) { mixin(S_TRACE);
- if (_change && _name != name) _change();
- _name = name;
- return true;
- }
- return false;
- }
- /// ??????????????????????????
- /// ????????true????
- const
- private bool canAppend(F)(string name) { mixin(S_TRACE);
- static if (is(F:Flag)) {
- name = validName(name);
- if (name.length == 0) { mixin(S_TRACE);
- return false;
- }
- foreach (flag; _flags) { mixin(S_TRACE);
- if (icmp(flag.name, name) == 0) { mixin(S_TRACE);
- return false;
- }
- }
- return true;
- } else static if (is(F:Step)) {
- name = validName(name);
- if (name.length == 0) { mixin(S_TRACE);
- return false;
- }
- foreach (step; _steps) { mixin(S_TRACE);
- if (icmp(step.name, name) == 0) { mixin(S_TRACE);
- return false;
- }
- }
- return true;
- } else { mixin(S_TRACE);
- static assert (is(F:FlagDir));
- return canAppendSub(name);
- }
- }
- const
- private bool canAppendFlag(in Flag f) { mixin(S_TRACE);
- return canAppend!Flag(f.name);
- }
- /// ditto
- const
- private bool canAppendStep(in Step f) { mixin(S_TRACE);
- return canAppend!Step(f.name);
- }
- /// ditto
- const
- bool canAppendSub(string name) { mixin(S_TRACE);
- name = validName(name);
- if (name.length == 0) { mixin(S_TRACE);
- return false;
- }
- foreach (dir; _subdir) { mixin(S_TRACE);
- if (icmp(dir.name, name) == 0) { mixin(S_TRACE);
- return false;
- }
- }
- return true;
- }
- /// ????????????????????true????
- /// ?????????????????????????????????????
- const
- bool canAppendSub2(in FlagDir ndir) { mixin(S_TRACE);
- if (this == ndir.parent) { mixin(S_TRACE);
- return true;
- }
- Rebindable!(const(FlagDir)) p = this;
- do { mixin(S_TRACE);
- if (p.get == ndir) { mixin(S_TRACE);
- // ????????????????????????????????????
- return false;
- }
- p = p.parent;
- } while (p.get !is null);
- return canAppendSub(ndir.name);
- }
- private bool __add(F)(ref F[] arr, F item, bool delegate(in F) canAppend) { mixin(S_TRACE);
- if (canAppend(item) || item.parent is this) { mixin(S_TRACE);
- if (item.parent is this && arr[$ - 1] is item) return true;
- if (item.parent !is null) { mixin(S_TRACE);
- item.parent.remove(item);
- }
- item.parent = this;
- arr ~= item;
- item.changeHandler = _change;
- if (_change) _change();
- return true;
- }
- return false;
- }
- /// ???????????????????????
- bool add(Flag flag) { mixin(S_TRACE);
- return __add!(Flag)(_flags, flag, &canAppendFlag);
- }
- /// ditto
- bool add(Step step) { mixin(S_TRACE);
- return __add!(Step)(_steps, step, &canAppendStep);
- }
- /// ditto
- bool add(FlagDir sub) { mixin(S_TRACE);
- if (__add!(FlagDir)(_subdir, sub, &canAppendSub2)) { mixin(S_TRACE);
- sub.sorterImpl = _sorter;
- return true;
- }
- return false;
- }
- /// ditto
- bool insert(int index, FlagDir sub) { mixin(S_TRACE);
- if (_subdir.length == index) return add(sub);
- if (canAppendSub2(sub) || sub.parent is this) { mixin(S_TRACE);
- if (sub.parent is this && _subdir[index] is sub) return true;
- if (sub.parent !is null) { mixin(S_TRACE);
- sub.parent.remove(sub);
- }
- sub.parent = this;
- _subdir = _subdir[0 .. index] ~ sub ~ _subdir[index .. $];
- sub.changeHandler = _change;
- if (_change) _change();
- return true;
- }
- return false;
- }
- private bool __remove(T)(ref T[] arr, T e) { mixin(S_TRACE);
- for (int i = 0; i < arr.length; i++) { mixin(S_TRACE);
- if (icmp(e.name, arr[i].name) == 0) { mixin(S_TRACE);
- e.parent = null;
- arr[i].changeHandler = null;
- arr = arr[0 .. i] ~ arr[i + 1 .. $];
- if (_change) _change();
- return true;
- }
- }
- return false;
- }
- /// ???????????????????????
- void remove(Flag flag) { mixin(S_TRACE);
- __remove(_flags, flag);
- }
- /// ditto
- void remove(Step step) { mixin(S_TRACE);
- __remove(_steps, step);
- }
- /// ditto
- void remove(FlagDir dir) { mixin(S_TRACE);
- if (__remove(_subdir, dir)) { mixin(S_TRACE);
- dir.sorterImpl = null;
- }
- }
- void removeAll() { mixin(S_TRACE);
- foreach (e; _flags) {
- e.parent = null;
- e.changeHandler = null;
- if (_change) _change();
- }
- _flags = [];
- foreach (e; _steps) {
- e.parent = null;
- e.changeHandler = null;
- if (_change) _change();
- }
- _steps = [];
- foreach (e; _subdir) {
- e.parent = null;
- e.changeHandler = null;
- if (_change) _change();
- }
- _subdir = [];
- }
- /// ??????????
- @property
- FlagDir[] subDirs() { mixin(S_TRACE);
- return _subdir;
- }
- /// ?????
- @property
- Flag[] flags() { mixin(S_TRACE);
- return _flags;
- }
- /// ??????
- @property
- Step[] steps() { mixin(S_TRACE);
- return _steps;
- }
- /// ???????????????????????????????true?
- const
- bool containsFlag(string name) { mixin(S_TRACE);
- return getFlag(name) !is null;
- }
- /// ditto
- const
- bool containsStep(string name) { mixin(S_TRACE);
- return getStep(name) !is null;
- }
- /// ditto
- const
- bool containsSubDir(string name) { mixin(S_TRACE);
- return getStep(name) !is null;
- }
- /// ?????????????????index????
- /// ????????-1????
- const
- int indexOf(string name) { mixin(S_TRACE);
- return .cCountUntil!("0 == icmp(a.name, b)")(_subdir, name);
- }
- /// ?????????????????
- void swapDir(int index1, int index2) { mixin(S_TRACE);
- if (index1 == index2) return;
- enforce(0 <= index1 && index1 < _subdir.length);
- enforce(0 <= index2 && index2 < _subdir.length);
- if (_change) _change();
- std.algorithm.swap(_subdir[index1], _subdir[index2]);
- }
- private static F __get(F)(F[] arr, string name) { mixin(S_TRACE);
- foreach (f; arr) { mixin(S_TRACE);
- if (icmp(f.name, name) == 0) { mixin(S_TRACE);
- return f;
- }
- }
- return null;
- }
- /// ??????????????????????????????
- /// ????????null????
- Flag getFlag(string name) { mixin(S_TRACE);
- return __get!(Flag)(_flags, name);
- }
- /// ditto
- const
- const(Flag) getFlag(string name) { mixin(S_TRACE);
- return __get!(const Flag)(_flags, name);
- }
- /// ditto
- Step getStep(string name) { mixin(S_TRACE);
- return __get!(Step)(_steps, name);
- }
- /// ditto
- const
- const(Step) getStep(string name) { mixin(S_TRACE);
- return __get!(const Step)(_steps, name);
- }
- /// ditto
- FlagDir getSubDir(string name) { mixin(S_TRACE);
- return __get!(FlagDir)(_subdir, name);
- }
- /// ditto
- const
- const(FlagDir) getSubDir(string name) { mixin(S_TRACE);
- return __get!(const FlagDir)(_subdir, name);
- }
- /// ??????????????????????
- /// ????????????????
- @property
- Flag[] allFlags() { mixin(S_TRACE);
- Flag[] r;
- foreach (flg; _flags) { mixin(S_TRACE);
- r ~= flg;
- }
- foreach (dir; _subdir) { mixin(S_TRACE);
- r ~= dir.allFlags;
- }
- return r;
- }
- /// ditto
- @property
- const
- const(Flag)[] allFlags() { mixin(S_TRACE);
- const(Flag)[] r;
- foreach (flg; _flags) { mixin(S_TRACE);
- r ~= flg;
- }
- foreach (dir; _subdir) { mixin(S_TRACE);
- r ~= dir.allFlags;
- }
- return r;
- }
- /// ditto
- @property
- Step[] allSteps() { mixin(S_TRACE);
- Step[] r;
- foreach (step; _steps) { mixin(S_TRACE);
- r ~= step;
- }
- foreach (dir; _subdir) { mixin(S_TRACE);
- r ~= dir.allSteps;
- }
- return r;
- }
- /// ditto
- @property
- const
- const(Step)[] allSteps() { mixin(S_TRACE);
- const(Step)[] r;
- foreach (step; _steps) { mixin(S_TRACE);
- r ~= step;
- }
- foreach (dir; _subdir) { mixin(S_TRACE);
- r ~= dir.allSteps;
- }
- return r;
- }
- /// ????????????????true?
- @property
- const
- bool hasFlag() { mixin(S_TRACE);
- if (_flags.length) return true;
- foreach (dir; _subdir) { mixin(S_TRACE);
- if (dir.hasFlag) return true;
- }
- return false;
- }
- /// ditto
- @property
- const
- bool hasStep() { mixin(S_TRACE);
- if (_steps.length) return true;
- foreach (dir; _subdir) { mixin(S_TRACE);
- if (dir.hasStep) return true;
- }
- return false;
- }
- /// ???????????????????
- void sortSubDirs(bool sub = false) { mixin(S_TRACE);
- bool cmps(in FlagDir a, in FlagDir b) { mixin(S_TRACE);
- if (_sorter) { mixin(S_TRACE);
- return _sorter(a.name, b.name) < 0;
- } else { mixin(S_TRACE);
- return cmp(a.name, b.name) < 0;
- }
- }
- if (!isSortedDlg!(FlagDir)(_subdir, &cmps)) { mixin(S_TRACE);
- if (_change) _change();
- _subdir = sortDlg!(FlagDir)(_subdir, &cmps);
- }
- if (sub) { mixin(S_TRACE);
- foreach (d; _subdir) { mixin(S_TRACE);
- d.sortSubDirs(true);
- }
- }
- }
- /// ditto
- void sortFlags(bool sub = false) { mixin(S_TRACE);
- bool cmps(in Flag a, in Flag b) { mixin(S_TRACE);
- if (_sorter) { mixin(S_TRACE);
- return _sorter(a.name, b.name) < 0;
- } else { mixin(S_TRACE);
- return cmp(a.name, b.name) < 0;
- }
- }
- if (!isSortedDlg!(Flag)(_flags, &cmps)) { mixin(S_TRACE);
- if (_change) _change();
- _flags = sortDlg!(Flag)(_flags, &cmps);
- }
- if (sub) { mixin(S_TRACE);
- foreach (d; _subdir) { mixin(S_TRACE);
- d.sortFlags(true);
- }
- }
- }
- /// ditto
- void sortSteps(bool sub = false) { mixin(S_TRACE);
- bool cmps(in Step a, in Step b) { mixin(S_TRACE);
- if (_sorter) { mixin(S_TRACE);
- return _sorter(a.name, b.name) < 0;
- } else { mixin(S_TRACE);
- return cmp(a.name, b.name) < 0;
- }
- }
- if (!isSortedDlg!(Step)(_steps, &cmps)) { mixin(S_TRACE);
- if (_change) _change();
- _steps = sortDlg!(Step)(_steps, &cmps);
- }
- if (sub) { mixin(S_TRACE);
- foreach (d; _subdir) { mixin(S_TRACE);
- d.sortSteps(true);
- }
- }
- }
- /// ?????????????????
- @property
- const
- string path() { mixin(S_TRACE);
- if (_parent !is null) { mixin(S_TRACE);
- return _parent.path ~ _name ~ SEPARATOR;
- } else { mixin(S_TRACE);
- return "";
- }
- }
- /// ?????????????????????????????????????
- void toNode(ref XNode e) { mixin(S_TRACE);
- auto fe = e.newElement("Flags");
- toNodeFlags(fe);
- auto se = e.newElement("Steps");
- toNodeSteps(se);
- }
- private void toNodeFlags(ref XNode e) { mixin(S_TRACE);
- foreach (flag; flags) { mixin(S_TRACE);
- flag.toNode(e);
- foreach (dir; _subdir) { mixin(S_TRACE);
- dir.toNodeFlags(e);
- }
- }
- }
- private void toNodeSteps(ref XNode e) { mixin(S_TRACE);
- foreach (step; steps) { mixin(S_TRACE);
- step.toNode(e);
- foreach (dir; _subdir) { mixin(S_TRACE);
- dir.toNodeSteps(e);
- }
- }
- }
- /// ??????????????????????????????
- /// ????????
- static string basename(string path) { mixin(S_TRACE);
- int sepLen = SEPARATOR.length;
- if (path.length < sepLen) { mixin(S_TRACE);
- return path;
- }
- if (endsWith(path, SEPARATOR.dup)) { mixin(S_TRACE);
- path = path[0 .. $ - sepLen];
- }
- for (int i = path.length - sepLen; i >= 0; i--) { mixin(S_TRACE);
- if (path[i .. i + sepLen] == SEPARATOR) { mixin(S_TRACE);
- return path[i + sepLen .. $];
- }
- }
- return path;
- } unittest { mixin(S_TRACE);
- debug mixin(UTPerf);
- assert (FlagDir.basename("\\test\\") == "test");
- assert (FlagDir.basename("\\aaa\\test") == "test");
- assert (FlagDir.basename("test") == "test");
- assert (FlagDir.basename("\\") == "");
- assert (FlagDir.basename("") == "");
- }
- /// ???????????????
- /// ??????????????????????true????
- /// ????????????????????????
- bool has(string path) { mixin(S_TRACE);
- path = .toLower(path);
- auto tpath = .toLower(this.path);
- int len = path.length;
- int tlen = tpath.length;
- int sepLen = SEPARATOR.length;
- return (len <= tlen) && (tpath[0 .. len] == path);
- } unittest { mixin(S_TRACE);
- debug mixin(UTPerf);
- auto dir1 = new FlagDir(cast(CWXPath) null);
- auto dir2 = new FlagDir("aaaaA");
- dir1.add(dir2);
- auto dir3 = new FlagDir("fsadfawegGGGg");
- dir2.add(dir3);
- auto dir4 = new FlagDir(cast(CWXPath) null);
- auto dir5 = new FlagDir("aAAAA");
- dir4.add(dir5);
- auto dir6 = new FlagDir("fsadFAwegGGGga");
- dir5.add(dir6);
- assert (dir1.has(dir1.path));
- assert (!dir1.has(dir2.path));
- assert (!dir1.has(dir3.path));
- assert (dir1.has(dir4.path));
- assert (!dir1.has(dir5.path));
- assert (!dir1.has(dir6.path));
- assert (dir2.has(dir1.path));
- assert (dir2.has(dir2.path));
- assert (!dir2.has(dir3.path));
- assert (dir2.has(dir4.path));
- assert (dir2.has(dir5.path));
- assert (!dir2.has(dir6.path));
- assert (dir3.has(dir1.path));
- assert (dir3.has(dir2.path));
- assert (dir3.has(dir3.path));
- assert (dir3.has(dir4.path));
- assert (dir3.has(dir5.path));
- assert (!dir3.has(dir6.path));
- assert (dir4.has(dir1.path));
- assert (!dir4.has(dir2.path));
- assert (!dir4.has(dir3.path));
- assert (dir4.has(dir4.path));
- assert (!dir4.has(dir5.path));
- assert (!dir4.has(dir6.path));
- assert (dir5.has(dir1.path));
- assert (dir5.has(dir2.path));
- assert (!dir5.has(dir3.path));
- assert (dir5.has(dir4.path));
- assert (dir5.has(dir5.path));
- assert (!dir5.has(dir6.path));
- assert (dir6.has(dir1.path));
- assert (dir6.has(dir2.path));
- assert (!dir6.has(dir3.path));
- assert (dir6.has(dir4.path));
- assert (dir6.has(dir5.path));
- assert (dir6.has(dir6.path));
- }
- /// path????????????????????
- static string up(string path) { mixin(S_TRACE);
- int sepLen = SEPARATOR.length;
- if (path.length < sepLen) { mixin(S_TRACE);
- return null;
- }
- if (path[$ - sepLen .. $] == SEPARATOR) { mixin(S_TRACE);
- path = path[0 .. $ - sepLen];
- }
- for (int i = path.length - sepLen; i >= 0; i--) { mixin(S_TRACE);
- if (path[i .. i + sepLen] == SEPARATOR) { mixin(S_TRACE);
- return path[0 .. i + sepLen];
- }
- }
- return "";
- } unittest { mixin(S_TRACE);
- debug mixin(UTPerf);
- assert (FlagDir.up("test\\") == "");
- assert (FlagDir.up("\\aaa\\test") == "\\aaa\\");
- assert (FlagDir.up("\\aaa\\test\\t\\") == "\\aaa\\test\\");
- assert (FlagDir.up("test") == "");
- assert (FlagDir.up("") is null);
- }
- /// appendFromXML()?????
- /// See_Also: appendFromXML()
- static enum AppendXmlResult {
- /// ???????????????
- DIR_SUCCESS,
- /// ?????????????????
- FLAG_STEP_SUCCESS,
- /// ????????
- FAIL,
- /// ?????????????????????????????
- FLAG_STEP_ON_DIR,
- /// ??????????????????????
- ON_DIR,
- }
- private static bool __loadFS(string Fs, string Fg, F)
- (ref XNode node, FlagDir p, out F[string] c, string delegate(string, string) createNewName, bool copy, in XMLInfo ver) { mixin(S_TRACE);
- bool ret = true;
- node.onTag[Fs] = (ref XNode node) { mixin(S_TRACE);
- if (!ret) return;
- node.onTag[Fg] = (ref XNode n) { mixin(S_TRACE);
- if (!ret) return;
- auto f = F.createFromNode(n, ver);
- if (!p.canAppend!F(f.name)) { mixin(S_TRACE);
- if (copy) { mixin(S_TRACE);
- f.name = createNewName(f.name, "");
- } else { mixin(S_TRACE);
- ret = false;
- return;
- }
- }
- c[n.childText("Name", true)] = f;
- };
- node.parse();
- };
- node.parse();
- return ret;
- }
- private bool loadFlagAndSteps
- (ref XNode node, out Flag[string] cFlags, out Step[string] cSteps, bool copy, in XMLInfo ver) { mixin(S_TRACE);
- try { mixin(S_TRACE);
- if (!__loadFS!("Flags", "Flag", Flag)(node, this, cFlags, &createNewFlagName, copy, ver)) { mixin(S_TRACE);
- .removeAll(cFlags);
- .removeAll(cSteps);
- return false;
- }
- if (!__loadFS!("Steps", "Step", Step)(node, this, cSteps, &createNewStepName, copy, ver)) { mixin(S_TRACE);
- .removeAll(cFlags);
- .removeAll(cSteps);
- return false;
- }
- foreach (v; cFlags.values) { mixin(S_TRACE);
- this.add(v);
- }
- foreach (v; cSteps.values) { mixin(S_TRACE);
- this.add(v);
- }
- return true;
- } catch (Exception e) {
- .removeAll(cFlags);
- .removeAll(cSteps);
- return false;
- }
- }
- private FlagDir loadSubs
- (ref XNode node, out Flag[string] cFlags, out Step[string] cSteps, bool copy, in XMLInfo ver) { mixin(S_TRACE);
- try { mixin(S_TRACE);
- auto subName = basename(node.attr("path", true));
- if (subName.length == 0) { mixin(S_TRACE);
- subName = validName(node.attr("rootName", true));
- }
- if (!canAppendSub(subName)) { mixin(S_TRACE);
- if (copy) { mixin(S_TRACE);
- subName = createNewDirName(subName, "");
- } else { mixin(S_TRACE);
- return null;
- }
- }
- auto sub = new FlagDir(subName);
- if (!sub.loadFlagAndSteps(node, cFlags, cSteps, false, ver)) { mixin(S_TRACE);
- assert (cFlags.length == 0);
- assert (cSteps.length == 0);
- return null;
- }
- bool ret = true;
- node.onTag["FlagDirectory"] = (ref XNode n) { mixin(S_TRACE);
- if (!ret) return;
- if (!sub.loadSubs(n, cFlags, cSteps, false, ver)) { mixin(S_TRACE);
- ret = false;
- return;
- }
- };
- node.parse();
- if (ret) { mixin(S_TRACE);
- this.add(sub);
- return sub;
- }
- } catch (Exception e) {
- }
- .removeAll(cFlags);
- .removeAll(cSteps);
- return null;
- }
- private bool readAtt(in XNode node, out string rootId, out string path, out bool sameTree) { mixin(S_TRACE);
- path = null;
- sameTree = false;
- rootId = node.attr(XML_ATT_ROOT_ID, false);
- path = node.attr(XML_ATT_PATH, false);
- if (rootId !is null && path !is null) { mixin(S_TRACE);
- sameTree = this.root.id == rootId;
- return true;
- } else { mixin(S_TRACE);
- return false;
- }
- }
- /// XML???????????????????true????
- /// getXml()?????XML???????????false????
- /// ???copy = false??????????????false???:
- /// (1) ??????????????????(???????????????????????)?
- /// (2) ????????/???????????/?????????????
- /// (3) ????????????????????
- /// (4) ?????????????????????????????????????
- /// copy = true??????????????/???/???????????" (??)"?????
- /// Params:
- /// xml = XML??
- /// copy = ???????true???????false?
- /// dirMode = ?????????????????
- /// newPath = AppendXmlResult.DIR_SUCCESS???????????????????????????
- /// cFlags = ???????????????????????????????????
- /// cSteps = ?????????????????????????????????????
- /// Returns: XML????????????
- /// See_Also: getXml(FlagDir, Flag[], Step[]), getXml(FlagDir)
- AppendXmlResult appendFromXML(string xml, in XMLInfo ver, bool copy, bool dirMode,
- out Flag[string] cFlags, out Step[string] cSteps, out string newPath, out string rootId) { mixin(S_TRACE);
- newPath = null;
- rootId = "";
- try { mixin(S_TRACE);
- scope doc = XNode.parse(xml);
- rootId = doc.attr(XML_ATT_ROOT_ID, false, "");
- if (doc.name == XML_ROOT_FLAGS_AND_STEPS) { mixin(S_TRACE);
- string path;
- bool sameTree;
- if (readAtt(doc, rootId, path, sameTree)) { mixin(S_TRACE);
- if (!copy && sameTree && icmp(this.path, path) == 0) { mixin(S_TRACE);
- // ???????????????????????????
- doc.onTag["Flags"] = (ref XNode node) { mixin(S_TRACE);
- doc.onTag["Flag"] = (ref XNode node) { mixin(S_TRACE);
- add(getFlag(node.childText("Name", true)));
- };
- node.parse();
- };
- doc.onTag["Steps"] = (ref XNode node) { mixin(S_TRACE);
- doc.onTag["Step"] = (ref XNode node) { mixin(S_TRACE);
- add(getStep(node.childText("Name", true)));
- };
- node.parse();
- };
- doc.parse();
- return AppendXmlResult.FLAG_STEP_ON_DIR;
- }
- if (loadFlagAndSteps(doc, cFlags, cSteps, copy, ver)) { mixin(S_TRACE);
- return AppendXmlResult.FLAG_STEP_SUCCESS;
- }
- }
- return AppendXmlResult.FAIL;
- }
- if (dirMode && doc.name == XML_ROOT_FLAG_DIRECTORY) { mixin(S_TRACE);
- return loadRootFlagDirectory(doc, ver, copy, cFlags, cSteps, newPath);
- }
- } catch (Exception e) {
- }
- return AppendXmlResult.FAIL;
- }
- private AppendXmlResult loadRootFlagDirectory(ref XNode node, in XMLInfo ver, bool copy,
- out Flag[string] cFlags, out Step[string] cSteps, out string newPath) { mixin(S_TRACE);
- newPath = null;
- string rootId;
- string path;
- bool sameTree;
- if (readAtt(node, rootId, path, sameTree)) { mixin(S_TRACE);
- auto dirName = basename(path);
- if (!copy) { mixin(S_TRACE);
- if (path.length == 0) { mixin(S_TRACE);
- // ??????????????
- return AppendXmlResult.FAIL;
- }
- if (sameTree && icmp(this.path, up(path)) == 0) { mixin(S_TRACE);
- // ???????????????????????????
- auto d = getSubDir(dirName);
- add(d);
- newPath = d.path;
- return AppendXmlResult.ON_DIR;
- }
- if (sameTree && has(path)) { mixin(S_TRACE);
- // ???????????????????
- return AppendXmlResult.FAIL;
- }
- if (!canAppendSub(dirName)) { mixin(S_TRACE);
- // ????????????????????
- return AppendXmlResult.FAIL;
- }
- }
- auto sub = loadSubs(node, cFlags, cSteps, copy, ver);
- if (sub) { mixin(S_TRACE);
- newPath = sub.path;
- } else { mixin(S_TRACE);
- return AppendXmlResult.FAIL;
- }
- return AppendXmlResult.DIR_SUCCESS;
- }
- return AppendXmlResult.FAIL;
- }
- /// ???????????????????????
- /// path??????????????
- static FlagDir searchPath(FlagDir root, string path) { mixin(S_TRACE);
- assert (root.parent is null);
- int sepLen = SEPARATOR.length;
- if (endsWith(path, FlagDir.SEPARATOR.dup)) { mixin(S_TRACE);
- path = path[0 .. $ - sepLen];
- }
- auto paths = std.string.split(path, SEPARATOR.dup);
- auto dir = root;
- loop: for (int lev = 0; lev < paths.length; lev++) { mixin(S_TRACE);
- foreach (sub; dir.subDirs) { mixin(S_TRACE);
- if (icmp(paths[lev], sub.name) == 0) { mixin(S_TRACE);
- if (lev < paths.length - 1) { mixin(S_TRACE);
- dir = sub;
- continue loop;
- } else { mixin(S_TRACE);
- return sub;
- }
- }
- }
- break;
- }
- return null;
- }
- /// ????????????????????????????
- /// ???????????
- /// ????????????????????????'\'??????????
- static string validName(string name) { mixin(S_TRACE);
- if (!name.length) { mixin(S_TRACE);
- name = "_";
- }
- string fsep = SEPARATOR;
- return replace(name, fsep, "");
- }
- /// base?????????????????????????
- /// base = xxxx????xxxx???????????????xxxx (2)?
- /// ???xxxx (2)????????????xxxx (3)……???????
- /// ???????????????????
- string createNewFlagName(string base, string oldName) { mixin(S_TRACE);
- return createNewName(validName(base), (string name) { mixin(S_TRACE);
- if (oldName && oldName.length && oldName == name) return true;
- return canAppend!Flag(name);
- });
- }
- /// ditto
- string createNewStepName(string base, string oldName) { mixin(S_TRACE);
- return createNewName(validName(base), (string name) { mixin(S_TRACE);
- if (oldName && oldName.length && oldName == name) return true;
- return canAppend!Step(name);
- });
- }
- /// ditto
- string createNewDirName(string base, string oldName) { mixin(S_TRACE);
- return createNewName(validName(base), (string name) { mixin(S_TRACE);
- if (oldName && oldName.length && oldName == name) return true;
- return canAppendSub(name);
- });
- }
- /// ??????n????????
- private string[] createNewNames(F)(string base, size_t n, in string[] oldNames)
- out (value) { mixin(S_TRACE);
- assert (value.length == n);
- } body { mixin(S_TRACE);
- auto oldSet = new HashSet!string;
- foreach (name; oldNames) oldSet.add(name.toLower());
- auto set = new HashSet!string;
- string[] r;
- foreach (i; 0..n) { mixin(S_TRACE);
- auto name = createNewName(validName(base), (string name) { mixin(S_TRACE);
- return (canAppend!F(name) || oldSet.contains(name.toLower())) && !set.contains(name.toLower());
- });
- set.add(name.toLower());
- r ~= name;
- }
- return r;
- }
- /// ditto
- string[] createNewFlagNames(string base, size_t n, in string[] oldNames)
- out (value) { mixin(S_TRACE);
- assert (value.length == n);
- } body { mixin(S_TRACE);
- return createNewNames!Flag(base, n, oldNames);
- }
- /// ditto
- string[] createNewStepNames(string base, size_t n, in string[] oldNames)
- out (value) { mixin(S_TRACE);
- assert (value.length == n);
- } body { mixin(S_TRACE);
- return createNewNames!Step(base, n, oldNames);
- }
- /// ditto
- string[] createNewDirNames(string base, size_t n, in string[] oldNames)
- out (value) { mixin(S_TRACE);
- assert (value.length == n);
- } body { mixin(S_TRACE);
- return createNewNames!FlagDir(base, n, oldNames);
- }
- /// ??????????????
- /// Params:
- /// path = ???
- /// create = true????????????????????
- /// Returns: ???????????????????????null?
- FlagDir findPath(string path, bool create) { mixin(S_TRACE);
- if (path.length == 0) { mixin(S_TRACE);
- return root;
- } else { mixin(S_TRACE);
- string fsep = SEPARATOR;
- auto paths = std.string.split(path, fsep);
- if (paths.length == 0) { mixin(S_TRACE);
- return root;
- }
- return root.__findPath(paths[0 .. $ - 1], create);
- }
- }
- const
- const(FlagDir) findPath(string path) { mixin(S_TRACE);
- if (path.length == 0) { mixin(S_TRACE);
- return root;
- } else { mixin(S_TRACE);
- string fsep = SEPARATOR;
- auto paths = std.string.split(path, fsep);
- if (paths.length == 0) { mixin(S_TRACE);
- return root;
- }
- return root.__findPath(paths[0 .. $ - 1]);
- }
- }
- private FlagDir __findPath(string[] paths, bool create) { mixin(S_TRACE);
- auto sub = getSubDir(paths[0]);
- if (sub is null) { mixin(S_TRACE);
- if (create) { mixin(S_TRACE);
- if (canAppendSub(paths[0])) { mixin(S_TRACE);
- sub = new FlagDir(paths[0]);
- this.add(sub);
- } else { mixin(S_TRACE);
- return null;
- }
- } else { mixin(S_TRACE);
- return null;
- }
- }
- if (paths.length == 1) { mixin(S_TRACE);
- return sub;
- } else { mixin(S_TRACE);
- return sub.__findPath(paths[1 .. $], create);
- }
- }
- const
- private const(FlagDir) __findPath(string[] paths) { mixin(S_TRACE);
- auto sub = getSubDir(paths[0]);
- if (sub is null) { mixin(S_TRACE);
- return null;
- }
- if (paths.length == 1) { mixin(S_TRACE);
- return sub;
- } else { mixin(S_TRACE);
- return sub.__findPath(paths[1 .. $]);
- }
- }
- /// ??????????????????
- /// Params:
- /// path = ???
- /// Returns: ????????????????????null?
- Flag findFlag(string path) { mixin(S_TRACE);
- if (path.length > 0) { mixin(S_TRACE);
- auto dir = findPath(up(path), false);
- if (dir !is null) { mixin(S_TRACE);
- return dir.getFlag(basename(path));
- }
- }
- return null;
- }
- /// ditto
- const
- const(Flag) findFlag(string path) { mixin(S_TRACE);
- if (path.length > 0) { mixin(S_TRACE);
- auto dir = findPath(up(path));
- if (dir !is null) { mixin(S_TRACE);
- return dir.getFlag(basename(path));
- }
- }
- return null;
- }
- /// ???????????????????
- /// Params:
- /// path = ???
- /// Returns: ?????????????????????null?
- Step findStep(string path) { mixin(S_TRACE);
- if (path.length > 0) { mixin(S_TRACE);
- auto dir = findPath(up(path), false);
- if (dir !is null) { mixin(S_TRACE);
- return dir.getStep(basename(path));
- }
- }
- return null;
- }
- const
- const(Step) findStep(string path) { mixin(S_TRACE);
- if (path.length > 0) { mixin(S_TRACE);
- auto dir = findPath(up(path));
- if (dir !is null) { mixin(S_TRACE);
- return dir.getStep(basename(path));
- }
- }
- return null;
- }
- /// ??????????????????????????????
- const
- void toNodeAll(ref XNode node) { mixin(S_TRACE);
- auto fe = node.newElement("Flags");
- foreach (flag; allFlags) { mixin(S_TRACE);
- flag.toNode(fe);
- }
- auto se = node.newElement("Steps");
- foreach (step; allSteps) { mixin(S_TRACE);
- step.toNode(se);
- }
- }
- /// XML????????????????????????????
- /// Params:
- /// node = ????
- /// change = ????????????
- /// Returns: ??????????
- static FlagDir fromXmlNode(ref XNode node, CWXPath owner, void delegate() change, in XMLInfo ver) { mixin(S_TRACE);
- auto root = new FlagDir(owner);
- node.onTag["Flags"] = (ref XNode node) { mixin(S_TRACE);
- __fromXmlNode!(Flag)(node, root, "Flag", &Flag.createFromNode, ver);
- };
- node.onTag["Steps"] = (ref XNode node) { mixin(S_TRACE);
- __fromXmlNode!(Step)(node, root, "Step", &Step.createFromNode, ver);
- };
- node.parse();
- root.changeHandler = change;
- return root;
- }
- private static void __fromXmlNode(E)(ref XNode node,
- FlagDir root, string es, E function(ref XNode, in XMLInfo) pfunc, in XMLInfo ver) { mixin(S_TRACE);
- node.onTag[es] = (ref XNode e) { mixin(S_TRACE);
- string path = e.childText("Name", false);
- if (path) { mixin(S_TRACE);
- auto parent = up(path);
- auto dir = parent !is null ? root.findPath(parent, true) : root;
- auto f = pfunc(e, ver);
- if (!f || !dir.canAppend!E(f.name)) { mixin(S_TRACE);
- throw new FlagException(es ~ " parse error: " ~ path);
- }
- dir.add(f);
- } else { mixin(S_TRACE);
- throw new FlagException(es ~ " name not found.");
- }
- };
- node.parse();
- root.sortSubDirs(true);
- root.sortFlags(true);
- root.sortSteps(true);
- }
- /// ???????????????
- /// ?????????????????????
- /// uc??????????
- bool rename(string name, UseCounter uc) { mixin(S_TRACE);
- auto flags = allFlags;
- auto oldFlagPaths = new string[flags.length];
- foreach (i, flag; flags) { mixin(S_TRACE);
- oldFlagPaths[i] = flag.path;
- }
- auto steps = allSteps;
- auto oldStepPaths = new string[steps.length];
- foreach (i, step; steps) { mixin(S_TRACE);
- oldStepPaths[i] = step.path;
- }
- string p = this.path;
- size_t plen = p.length;
- if (!.endsWith(p, FlagDir.SEPARATOR.idup)) { mixin(S_TRACE);
- plen += FlagDir.SEPARATOR.length;
- }
- if (!this.name(name)) { mixin(S_TRACE);
- return false;
- }
- p = this.path;
- foreach (path; oldFlagPaths) { mixin(S_TRACE);
- auto newPath = FlagDir.join(p, path[plen .. $]);
- uc.change(toFlagId(path), toFlagId(newPath));
- }
- foreach (path; oldStepPaths) { mixin(S_TRACE);
- auto newPath = FlagDir.join(p, path[plen .. $]);
- uc.change(toStepId(path), toStepId(newPath));
- }
- return true;
- }
- }