<commit_before>#include <cstring>
#include <algorithm>
#include <fstream>

#include "xml_parser.h"
#include "os.h"
#include "string.h"

namespace lms {
namespace internal {

template<typename T>
struct PutOnStack {
    std::stack<T> &stack;

    PutOnStack(std::stack<T> &stack, const T &obj) : stack(stack) {
        stack.push(obj);
    }

    ~PutOnStack() {
        stack.pop();
    }
};

bool evaluateSet(const std::string &condition,
                 const std::vector<std::string> &flags) {
    return std::find(flags.begin(), flags.end(), condition) != flags.end();
}

bool evaluateNotSet(const std::string &condition,
                    const std::vector<std::string> &flags) {
    return std::find(flags.begin(), flags.end(), condition) == flags.end();
}

bool evaluateAnyOf(const std::vector<std::string> &condition,
                   const std::vector<std::string> &flags) {
    return std::find_first_of(condition.begin(), condition.end(), flags.begin(),
                              flags.end()) != condition.end();
}

bool evaluateAllOf(const std::vector<std::string> &condition,
                   const std::vector<std::string> &flags) {
    for (const std::string &cond : condition) {
        if (std::find(flags.begin(), flags.end(), cond) == flags.end()) {
            return false;
        }
    }

    return true;
}

bool evaluateNothingOf(const std::vector<std::string> &condition,
                       const std::vector<std::string> &flags) {
    for (const std::string &cond : condition) {
        if (std::find(flags.begin(), flags.end(), cond) != flags.end()) {
            return false;
        }
    }

    return true;
}

void preprocessXML(pugi::xml_node node, const std::vector<std::string> &flags) {
    if (std::string("/framework/module/config") == node.path()) {
        // skip <config> nodes
        return;
    }

    for (pugi::xml_node child = node.child("if"); child;) {
        if (std::string("if") == child.name()) {
            bool result = false;

            pugi::xml_attribute setAttr = child.attribute("set");
            pugi::xml_attribute notSetAttr = child.attribute("notSet");
            pugi::xml_attribute anyOfAttr = child.attribute("anyOf");
            pugi::xml_attribute allOfAttr = child.attribute("allOf");
            pugi::xml_attribute nothingOfAttr = child.attribute("nothingOf");

            if (setAttr) {
                result = evaluateSet(setAttr.value(), flags);
            } else if (notSetAttr) {
                result = evaluateNotSet(notSetAttr.value(), flags);
            } else if (anyOfAttr) {
                result = evaluateAnyOf(split(anyOfAttr.value(), ','), flags);
            } else if (allOfAttr) {
                result = evaluateAllOf(split(allOfAttr.value(), ','), flags);
            } else if (nothingOfAttr) {
                result =
                    evaluateNothingOf(split(nothingOfAttr.value(), ','), flags);
            } else {
                std::cout << "Failed to preprocess XML <if>" << std::endl;
            }

            // if the condition evaluated to true
            if (result) {
                // then move all children of <if> to be siblings of <if>

                pugi::xml_node moveNode;
                while ((moveNode = child.first_child())) {
                    node.insert_move_after(moveNode, child);
                }

                node.remove_child(child);
            } else {
                node.remove_child(child);
            }

            // reset child
            child = node.first_child();
        } else {
            // go further
            child = child.next_sibling("if");
        }
    }

    for (pugi::xml_node child : node) {
        preprocessXML(child, flags);
    }
}

XmlParser::XmlParser(RuntimeInfo &info) : runtime(info) {}

void parseModuleConfig(pugi::xml_node node, Config &config,
                       const std::string &key) {
    for (auto subnode : node.children()) {
        if (subnode.type() == pugi::node_element) {
            std::string newKey = subnode.attribute("name").as_string();
            if (!key.empty()) {
                newKey = key + "." + newKey;
            }

            if (std::strcmp("group", subnode.name()) == 0) {
                parseModuleConfig(subnode, config, newKey);
            } else {
                config.set<std::string>(newKey, trim(subnode.child_value()));
            }
        }
    }
}

bool XmlParser::parseClock(pugi::xml_node node, ClockInfo &info) {
    std::string clockUnit;
    std::int64_t clockValue = 0;

    pugi::xml_attribute sleepAttr = node.attribute("sleep");
    pugi::xml_attribute compensateAttr = node.attribute("compensate");
    pugi::xml_attribute unitAttr = node.attribute("unit");
    pugi::xml_attribute valueAttr = node.attribute("value");
    pugi::xml_attribute watchDog = node.attribute("watchDog");

    info.slowWarnings = true;

    if (sleepAttr) {
        info.sleep = sleepAttr.as_bool();
    } else {
        // if not enabled attribute is given then the clock is considered
        // to be disabled
        info.sleep = false;
    }

    if (valueAttr) {
        clockValue = valueAttr.as_llong();
    } else {
        info.slowWarnings = false;
        return errorMissingAttr(node, valueAttr);
    }

    if (unitAttr) {
        clockUnit = unitAttr.value();
    } else {
        info.slowWarnings = false;
        return errorMissingAttr(node, unitAttr);
    }

    if (compensateAttr) {
        info.sleepCompensate = compensateAttr.as_bool();
    } else {
        info.sleepCompensate = false;
    }

    if (clockUnit == "hz") {
        info.cycle = Time::fromMicros(1000000 / clockValue);
    } else if (clockUnit == "ms") {
        info.cycle = Time::fromMillis(clockValue);
    } else if (clockUnit == "us") {
        info.cycle = Time::fromMicros(clockValue);
    } else {
        info.slowWarnings = false;
        return errorInvalidAttr(node, unitAttr, "ms/us/hz");
    }

    if (watchDog) {
        info.watchDogEnabled = true;
        if (clockUnit == "hz") {
            info.watchDog = Time::fromMicros(1000000 / watchDog.as_llong());
        } else if (clockUnit == "ms") {
            info.watchDog = Time::fromMillis(watchDog.as_llong());
        } else if (clockUnit == "us") {
            info.watchDog = Time::fromMicros(watchDog.as_llong());
        } else {
            info.watchDogEnabled = false;
            return errorInvalidAttr(node, watchDog, "ms/us/hz");
        }
    }

    return true;
}

bool XmlParser::parseInclude(pugi::xml_node node) {
    pugi::xml_attribute srcAttr = node.attribute("src");

    if(! srcAttr) return errorMissingAttr(node, srcAttr);

    std::string includePath = dirname(m_filestack.top()) + "/" + srcAttr.value();
    parseFile(includePath);
    return true;
}

bool XmlParser::parseModule(pugi::xml_node node, ModuleInfo &info) {
    pugi::xml_attribute nameAttr = node.attribute("name");
    pugi::xml_attribute libAttr = node.attribute("lib");
    pugi::xml_attribute classAttr = node.attribute("class");
    pugi::xml_attribute mainThreadAttr = node.attribute("mainThread");
    pugi::xml_attribute logLevelAttr = node.attribute("log");

    if(! nameAttr) return errorMissingAttr(node, nameAttr);
    if(! libAttr) return errorMissingAttr(node, libAttr);
    if(! classAttr) return errorMissingAttr(node, classAttr);

    info.name = nameAttr.as_string();
    info.lib = libAttr.as_string();
    info.clazz = classAttr.as_string();
    info.mainThread = mainThreadAttr.as_bool();

    logging::Level defaultLevel = logging::Level::ALL;
    if (logLevelAttr) {
        logging::levelFromName(logLevelAttr.as_string(), defaultLevel);
    }
    info.log = defaultLevel;

    // parse all channel mappings
    // TODO This now deprecated in favor for channelHint
    for (pugi::xml_node mappingNode : node.children("channelMapping")) {
        pugi::xml_attribute fromAttr = mappingNode.attribute("from");
        pugi::xml_attribute toAttr = mappingNode.attribute("to");
        pugi::xml_attribute priorityAttr = mappingNode.attribute("priority");

        if (!fromAttr) return errorMissingAttr(mappingNode, fromAttr);
        if (!toAttr) return errorMissingAttr(mappingNode, toAttr);

        int priority = priorityAttr ? priorityAttr.as_int() : 0;
        info.channelMapping[fromAttr.value()] =
            std::make_pair(toAttr.value(), priority);
    }

    for (pugi::xml_node channelNode : node.children("channelHint")) {
        pugi::xml_attribute nameAttr = channelNode.attribute("name");
        pugi::xml_attribute mapToAttr = channelNode.attribute("mapTo");
        pugi::xml_attribute priorityAttr = channelNode.attribute("priority");

        if (!nameAttr) return errorMissingAttr(channelNode, nameAttr);

        std::string mapTo = mapToAttr ? mapToAttr.value() : nameAttr.value();
        int priority = priorityAttr ? priorityAttr.as_int() : 0;

        info.channelMapping[nameAttr.value()] =
            std::make_pair(mapTo, priority);
    }

    // parse all config
    for (pugi::xml_node configNode : node.children("config")) {
        pugi::xml_attribute srcAttr = configNode.attribute("src");
        pugi::xml_attribute nameAttr = configNode.attribute("name");

        std::string name = "default";
        if (nameAttr) {
            name = nameAttr.value();
        }

        if (srcAttr) {
            std::string lconfPath = dirname(m_filestack.top()) + "/" + srcAttr.value();

            bool loadResult = info.configs[name].loadFromFile(lconfPath);
            if (!loadResult) {
                return errorFile(lconfPath);
            } else {
                m_files.push_back(lconfPath);
            }
        } else {
            // if there was no src attribut then parse the tag's content
            parseModuleConfig(configNode, info.configs[name], "");
        }
    }

    return true;
}

bool XmlParser::parseService(pugi::xml_node node, ServiceInfo &info) {
    pugi::xml_attribute nameAttr = node.attribute("name");
    pugi::xml_attribute libAttr = node.attribute("lib");
    pugi::xml_attribute classAttr = node.attribute("class");
    pugi::xml_attribute logLevelAttr = node.attribute("log");

    if(! nameAttr) return errorMissingAttr(node, nameAttr);
    if(! libAttr) return errorMissingAttr(node, libAttr);
    if(! classAttr) return errorMissingAttr(node, classAttr);

    info.name = nameAttr.as_string();
    info.lib = libAttr.as_string();
    info.clazz = classAttr.as_string();

    logging::Level defaultLevel = logging::Level::ALL;
    if (logLevelAttr) {
        logging::levelFromName(logLevelAttr.as_string(), defaultLevel);
    }
    info.log = defaultLevel;

    // parse all config
    for (pugi::xml_node configNode : node.children("config")) {
        pugi::xml_attribute srcAttr = configNode.attribute("src");
        pugi::xml_attribute nameAttr = configNode.attribute("name");

        std::string name = "default";
        if (nameAttr) {
            name = nameAttr.value();
        }

        if (srcAttr) {
            std::string lconfPath = dirname(m_filestack.top()) + "/"  + srcAttr.value();

            bool loadResult = info.configs[name].loadFromFile(lconfPath);
            if (!loadResult) {
                errorFile(lconfPath);
            } else {
                m_files.push_back(lconfPath);
            }
        } else {
            // if there was no src attribut then parse the tag's content
            parseModuleConfig(configNode, info.configs[name], "");
        }
    }

    return true;
}

bool XmlParser::parseFile(std::istream &is, const std::string &file) {
    PutOnStack<std::string> put(m_filestack, file);
    m_files.push_back(file);

    pugi::xml_document doc;
    pugi::xml_parse_result result = doc.load(is);
    if (!result) {
        return errorPugiParseResult(file, result);
    }

    pugi::xml_node rootNode = doc.child("lms");
    preprocessXML(rootNode, {});

    for (pugi::xml_node node : rootNode.children()) {
        if (std::string("clock") == node.name()) {
            if(!parseClock(node, runtime.clock)) return false;
        } else if (std::string("module") == node.name()) {
            ModuleInfo module;
            if(parseModule(node, module)) {
                runtime.modules.push_back(module);
            }
        } else if (std::string("include") == node.name()) {
            parseInclude(node);
        } else if (std::string("service") == node.name()) {
            ServiceInfo service;
            if(parseService(node, service)) {
                runtime.services.push_back(service);
            }
        } else {
            errorUnknownNode(node);
        }
    }

    return true;
}

bool XmlParser::parseFile(const std::string &file) {
    std::ifstream ifs(file);

    if (!ifs.is_open()) {
        return errorFile(file);
    }

    return parseFile(ifs, file);
}

std::vector<std::string> const &XmlParser::files() const { return m_files; }

std::vector<std::string> const &XmlParser::errors() const { return m_errors; }

bool XmlParser::errorMissingAttr(pugi::xml_node node,
                                 pugi::xml_attribute attr) {
    m_errors.push_back(std::string("Missing attribute ") + attr.name() +
                       " in node " + node.path());
    return false;
}

bool XmlParser::errorInvalidAttr(pugi::xml_node node, pugi::xml_attribute attr,
                                 const std::string &expectedValue) {
    m_errors.push_back(std::string("Invalid value for attribute ") +
                       attr.name() + " in node " + node.path() +
                       ", Value is \"" + attr.value() + "\" but expected \"" +
                       expectedValue + "\"");
    return false;
}

void XmlParser::errorInvalidNodeContent(pugi::xml_node node,
                                        const std::string &expected) {
    m_errors.push_back("Invalid text content in node " + node.path() +
                       ", content: \"" + node.child_value() +
                       "\", expected \"" + expected + "\"");
}

bool XmlParser::errorFile(const std::string &file) {
    m_errors.push_back("Could not open file " + file);
    return false;
}

bool XmlParser::errorPugiParseResult(const std::string &file,
                                     const pugi::xml_parse_result &result) {
    m_errors.push_back(std::string() + "Failed to parse " + file + " as XML: " +
                       std::to_string(result.offset) + " " +
                       result.description());
    return false;
}

bool XmlParser::errorUnknownNode(pugi::xml_node node) {
    m_errors.push_back("Unknown node " + node.path());
    return false;
}

} // namespace internal
} // namespace lms
<commit_msg>improved debug msg<commit_after>#include <cstring>
#include <algorithm>
#include <fstream>

#include "xml_parser.h"
#include "os.h"
#include "string.h"

namespace lms {
namespace internal {

template<typename T>
struct PutOnStack {
    std::stack<T> &stack;

    PutOnStack(std::stack<T> &stack, const T &obj) : stack(stack) {
        stack.push(obj);
    }

    ~PutOnStack() {
        stack.pop();
    }
};

bool evaluateSet(const std::string &condition,
                 const std::vector<std::string> &flags) {
    return std::find(flags.begin(), flags.end(), condition) != flags.end();
}

bool evaluateNotSet(const std::string &condition,
                    const std::vector<std::string> &flags) {
    return std::find(flags.begin(), flags.end(), condition) == flags.end();
}

bool evaluateAnyOf(const std::vector<std::string> &condition,
                   const std::vector<std::string> &flags) {
    return std::find_first_of(condition.begin(), condition.end(), flags.begin(),
                              flags.end()) != condition.end();
}

bool evaluateAllOf(const std::vector<std::string> &condition,
                   const std::vector<std::string> &flags) {
    for (const std::string &cond : condition) {
        if (std::find(flags.begin(), flags.end(), cond) == flags.end()) {
            return false;
        }
    }

    return true;
}

bool evaluateNothingOf(const std::vector<std::string> &condition,
                       const std::vector<std::string> &flags) {
    for (const std::string &cond : condition) {
        if (std::find(flags.begin(), flags.end(), cond) != flags.end()) {
            return false;
        }
    }

    return true;
}

void preprocessXML(pugi::xml_node node, const std::vector<std::string> &flags) {
    if (std::string("/framework/module/config") == node.path()) {
        // skip <config> nodes
        return;
    }

    for (pugi::xml_node child = node.child("if"); child;) {
        if (std::string("if") == child.name()) {
            bool result = false;

            pugi::xml_attribute setAttr = child.attribute("set");
            pugi::xml_attribute notSetAttr = child.attribute("notSet");
            pugi::xml_attribute anyOfAttr = child.attribute("anyOf");
            pugi::xml_attribute allOfAttr = child.attribute("allOf");
            pugi::xml_attribute nothingOfAttr = child.attribute("nothingOf");

            if (setAttr) {
                result = evaluateSet(setAttr.value(), flags);
            } else if (notSetAttr) {
                result = evaluateNotSet(notSetAttr.value(), flags);
            } else if (anyOfAttr) {
                result = evaluateAnyOf(split(anyOfAttr.value(), ','), flags);
            } else if (allOfAttr) {
                result = evaluateAllOf(split(allOfAttr.value(), ','), flags);
            } else if (nothingOfAttr) {
                result =
                    evaluateNothingOf(split(nothingOfAttr.value(), ','), flags);
            } else {
                std::cout << "Failed to preprocess XML <if>" << std::endl;
            }

            // if the condition evaluated to true
            if (result) {
                // then move all children of <if> to be siblings of <if>

                pugi::xml_node moveNode;
                while ((moveNode = child.first_child())) {
                    node.insert_move_after(moveNode, child);
                }

                node.remove_child(child);
            } else {
                node.remove_child(child);
            }

            // reset child
            child = node.first_child();
        } else {
            // go further
            child = child.next_sibling("if");
        }
    }

    for (pugi::xml_node child : node) {
        preprocessXML(child, flags);
    }
}

XmlParser::XmlParser(RuntimeInfo &info) : runtime(info) {}

void parseModuleConfig(pugi::xml_node node, Config &config,
                       const std::string &key) {
    for (auto subnode : node.children()) {
        if (subnode.type() == pugi::node_element) {
            std::string newKey = subnode.attribute("name").as_string();
            if (!key.empty()) {
                newKey = key + "." + newKey;
            }

            if (std::strcmp("group", subnode.name()) == 0) {
                parseModuleConfig(subnode, config, newKey);
            } else {
                config.set<std::string>(newKey, trim(subnode.child_value()));
            }
        }
    }
}

bool XmlParser::parseClock(pugi::xml_node node, ClockInfo &info) {
    std::string clockUnit;
    std::int64_t clockValue = 0;

    pugi::xml_attribute sleepAttr = node.attribute("sleep");
    pugi::xml_attribute compensateAttr = node.attribute("compensate");
    pugi::xml_attribute unitAttr = node.attribute("unit");
    pugi::xml_attribute valueAttr = node.attribute("value");
    pugi::xml_attribute watchDog = node.attribute("watchDog");

    info.slowWarnings = true;

    if (sleepAttr) {
        info.sleep = sleepAttr.as_bool();
    } else {
        // if not enabled attribute is given then the clock is considered
        // to be disabled
        info.sleep = false;
    }

    if (valueAttr) {
        clockValue = valueAttr.as_llong();
    } else {
        info.slowWarnings = false;
        return errorMissingAttr(node, valueAttr);
    }

    if (unitAttr) {
        clockUnit = unitAttr.value();
    } else {
        info.slowWarnings = false;
        return errorMissingAttr(node, unitAttr);
    }

    if (compensateAttr) {
        info.sleepCompensate = compensateAttr.as_bool();
    } else {
        info.sleepCompensate = false;
    }

    if (clockUnit == "hz") {
        info.cycle = Time::fromMicros(1000000 / clockValue);
    } else if (clockUnit == "ms") {
        info.cycle = Time::fromMillis(clockValue);
    } else if (clockUnit == "us") {
        info.cycle = Time::fromMicros(clockValue);
    } else {
        info.slowWarnings = false;
        return errorInvalidAttr(node, unitAttr, "ms/us/hz");
    }

    if (watchDog) {
        info.watchDogEnabled = true;
        if (clockUnit == "hz") {
            info.watchDog = Time::fromMicros(1000000 / watchDog.as_llong());
        } else if (clockUnit == "ms") {
            info.watchDog = Time::fromMillis(watchDog.as_llong());
        } else if (clockUnit == "us") {
            info.watchDog = Time::fromMicros(watchDog.as_llong());
        } else {
            info.watchDogEnabled = false;
            return errorInvalidAttr(node, watchDog, "ms/us/hz");
        }
    }

    return true;
}

bool XmlParser::parseInclude(pugi::xml_node node) {
    pugi::xml_attribute srcAttr = node.attribute("src");

    if(! srcAttr) return errorMissingAttr(node, srcAttr);

    std::string includePath = dirname(m_filestack.top()) + "/" + srcAttr.value();
    parseFile(includePath);
    return true;
}

bool XmlParser::parseModule(pugi::xml_node node, ModuleInfo &info) {
    pugi::xml_attribute nameAttr = node.attribute("name");
    pugi::xml_attribute libAttr = node.attribute("lib");
    pugi::xml_attribute classAttr = node.attribute("class");
    pugi::xml_attribute mainThreadAttr = node.attribute("mainThread");
    pugi::xml_attribute logLevelAttr = node.attribute("log");

    if(! nameAttr) return errorMissingAttr(node, nameAttr);
    if(! libAttr) return errorMissingAttr(node, libAttr);
    if(! classAttr) return errorMissingAttr(node, classAttr);

    info.name = nameAttr.as_string();
    info.lib = libAttr.as_string();
    info.clazz = classAttr.as_string();
    info.mainThread = mainThreadAttr.as_bool();

    logging::Level defaultLevel = logging::Level::ALL;
    if (logLevelAttr) {
        logging::levelFromName(logLevelAttr.as_string(), defaultLevel);
    }
    info.log = defaultLevel;

    // parse all channel mappings
    // TODO This now deprecated in favor for channelHint
    for (pugi::xml_node mappingNode : node.children("channelMapping")) {
        pugi::xml_attribute fromAttr = mappingNode.attribute("from");
        pugi::xml_attribute toAttr = mappingNode.attribute("to");
        pugi::xml_attribute priorityAttr = mappingNode.attribute("priority");

        if (!fromAttr) return errorMissingAttr(mappingNode, fromAttr);
        if (!toAttr) return errorMissingAttr(mappingNode, toAttr);

        int priority = priorityAttr ? priorityAttr.as_int() : 0;
        info.channelMapping[fromAttr.value()] =
            std::make_pair(toAttr.value(), priority);
    }

    for (pugi::xml_node channelNode : node.children("channelHint")) {
        pugi::xml_attribute nameAttr = channelNode.attribute("name");
        pugi::xml_attribute mapToAttr = channelNode.attribute("mapTo");
        pugi::xml_attribute priorityAttr = channelNode.attribute("priority");

        if (!nameAttr) return errorMissingAttr(channelNode, nameAttr);

        std::string mapTo = mapToAttr ? mapToAttr.value() : nameAttr.value();
        int priority = priorityAttr ? priorityAttr.as_int() : 0;

        info.channelMapping[nameAttr.value()] =
            std::make_pair(mapTo, priority);
    }

    // parse all config
    for (pugi::xml_node configNode : node.children("config")) {
        pugi::xml_attribute srcAttr = configNode.attribute("src");
        pugi::xml_attribute nameAttr = configNode.attribute("name");

        std::string name = "default";
        if (nameAttr) {
            name = nameAttr.value();
        }

        if (srcAttr) {
            std::string lconfPath = dirname(m_filestack.top()) + "/" + srcAttr.value();

            bool loadResult = info.configs[name].loadFromFile(lconfPath);
            if (!loadResult) {
                return errorFile(lconfPath);
            } else {
                m_files.push_back(lconfPath);
            }
        } else {
            // if there was no src attribut then parse the tag's content
            parseModuleConfig(configNode, info.configs[name], "");
        }
    }

    return true;
}

bool XmlParser::parseService(pugi::xml_node node, ServiceInfo &info) {
    pugi::xml_attribute nameAttr = node.attribute("name");
    pugi::xml_attribute libAttr = node.attribute("lib");
    pugi::xml_attribute classAttr = node.attribute("class");
    pugi::xml_attribute logLevelAttr = node.attribute("log");

    if(! nameAttr) return errorMissingAttr(node, nameAttr);
    if(! libAttr) return errorMissingAttr(node, libAttr);
    if(! classAttr) return errorMissingAttr(node, classAttr);

    info.name = nameAttr.as_string();
    info.lib = libAttr.as_string();
    info.clazz = classAttr.as_string();

    logging::Level defaultLevel = logging::Level::ALL;
    if (logLevelAttr) {
        logging::levelFromName(logLevelAttr.as_string(), defaultLevel);
    }
    info.log = defaultLevel;

    // parse all config
    for (pugi::xml_node configNode : node.children("config")) {
        pugi::xml_attribute srcAttr = configNode.attribute("src");
        pugi::xml_attribute nameAttr = configNode.attribute("name");

        std::string name = "default";
        if (nameAttr) {
            name = nameAttr.value();
        }

        if (srcAttr) {
            std::string lconfPath = dirname(m_filestack.top()) + "/"  + srcAttr.value();

            bool loadResult = info.configs[name].loadFromFile(lconfPath);
            if (!loadResult) {
                errorFile(lconfPath);
            } else {
                m_files.push_back(lconfPath);
            }
        } else {
            // if there was no src attribut then parse the tag's content
            parseModuleConfig(configNode, info.configs[name], "");
        }
    }

    return true;
}

bool XmlParser::parseFile(std::istream &is, const std::string &file) {
    PutOnStack<std::string> put(m_filestack, file);
    m_files.push_back(file);

    pugi::xml_document doc;
    pugi::xml_parse_result result = doc.load(is);
    if (!result) {
        return errorPugiParseResult(file, result);
    }

    pugi::xml_node rootNode = doc.child("lms");
    preprocessXML(rootNode, {});

    for (pugi::xml_node node : rootNode.children()) {
        if (std::string("clock") == node.name()) {
            if(!parseClock(node, runtime.clock)) return false;
        } else if (std::string("module") == node.name()) {
            ModuleInfo module;
            if(parseModule(node, module)) {
                runtime.modules.push_back(module);
            }
        } else if (std::string("include") == node.name()) {
            parseInclude(node);
        } else if (std::string("service") == node.name()) {
            ServiceInfo service;
            if(parseService(node, service)) {
                runtime.services.push_back(service);
            }
        } else {
            errorUnknownNode(node);
        }
    }

    return true;
}

bool XmlParser::parseFile(const std::string &file) {
    std::ifstream ifs(file);

    if (!ifs.is_open()) {
        return errorFile(file);
    }

    return parseFile(ifs, file);
}

std::vector<std::string> const &XmlParser::files() const { return m_files; }

std::vector<std::string> const &XmlParser::errors() const { return m_errors; }

bool XmlParser::errorMissingAttr(pugi::xml_node node,
                                 pugi::xml_attribute attr) {
    m_errors.push_back(std::string("Missing attribute ") + attr.name() +
                       " in node " + node.path() + " in file " + m_filestack.top());
    return false;
}

bool XmlParser::errorInvalidAttr(pugi::xml_node node, pugi::xml_attribute attr,
                                 const std::string &expectedValue) {
    m_errors.push_back(std::string("Invalid value for attribute ") +
                       attr.name() + " in node " + node.path() +
                       ", Value is \"" + attr.value() + "\" but expected \"" +
                       expectedValue + "\"");
    return false;
}

void XmlParser::errorInvalidNodeContent(pugi::xml_node node,
                                        const std::string &expected) {
    m_errors.push_back("Invalid text content in node " + node.path() +
                       ", content: \"" + node.child_value() +
                       "\", expected \"" + expected + "\"");
}

bool XmlParser::errorFile(const std::string &file) {
    m_errors.push_back("Could not open file " + file);
    return false;
}

bool XmlParser::errorPugiParseResult(const std::string &file,
                                     const pugi::xml_parse_result &result) {
    m_errors.push_back(std::string() + "Failed to parse " + file + " as XML: " +
                       std::to_string(result.offset) + " " +
                       result.description());
    return false;
}

bool XmlParser::errorUnknownNode(pugi::xml_node node) {
    m_errors.push_back("Unknown node " + node.path());
    return false;
}

} // namespace internal
} // namespace lms
<|endoftext|>


<commit_before>#include "node_operators.h"
#include "expression_graph.h"

#include "tensors/tensor_operators.h"

namespace marian {

ConstantNode::ConstantNode(Ptr<ExpressionGraph> graph,
                          const Shape& shape,
                          const Ptr<inits::NodeInitializer>& init,
                          Type value_type)
    : Node(graph, shape, value_type),
      init_(init),
      initialized_(false) {
  init_->setAllocator(graph->allocator());
  setTrainable(false);
}

size_t ConstantNode::allocate() {
  size_t elements = 0;
  if(!val_) {
    graph()->allocateForward(this);
    elements = val_->shape().elements();
  }
  return elements;
}

void ConstantNode::init() {
  if(!initialized_) {
    init_->apply(val_);
    initialized_ = true;
  }
  init_.reset();
}

ParamNode::ParamNode(Ptr<ExpressionGraph> graph,
                     const Shape& shape,
                     const Ptr<inits::NodeInitializer>& init,
                     bool fixed)
    : ParamNode(graph, shape, init, Type::float32, fixed) {}

ParamNode::ParamNode(Ptr<ExpressionGraph> graph,
                     const Shape& shape,
                     const Ptr<inits::NodeInitializer>& init,
                     const Type& valueType,
                     bool fixed)
    : Node(graph, shape, valueType),
      init_(init),
      initialized_(false) {
  init_->setAllocator(graph->allocator());
  setTrainable(!fixed);
  setMemoize(graph->isInference());
}

void ParamNode::init() {
  std::cerr << name() << " " << shape() << std::endl;
  if(!initialized_) {
    init_->apply(val_);
    initialized_ = true;
  }
  init_.reset();
}
}  // namespace marian
<commit_msg>remove debug code<commit_after>#include "node_operators.h"
#include "expression_graph.h"

#include "tensors/tensor_operators.h"

namespace marian {

ConstantNode::ConstantNode(Ptr<ExpressionGraph> graph,
                          const Shape& shape,
                          const Ptr<inits::NodeInitializer>& init,
                          Type value_type)
    : Node(graph, shape, value_type),
      init_(init),
      initialized_(false) {
  init_->setAllocator(graph->allocator());
  setTrainable(false);
}

size_t ConstantNode::allocate() {
  size_t elements = 0;
  if(!val_) {
    graph()->allocateForward(this);
    elements = val_->shape().elements();
  }
  return elements;
}

void ConstantNode::init() {
  if(!initialized_) {
    init_->apply(val_);
    initialized_ = true;
  }
  init_.reset();
}

ParamNode::ParamNode(Ptr<ExpressionGraph> graph,
                     const Shape& shape,
                     const Ptr<inits::NodeInitializer>& init,
                     bool fixed)
    : ParamNode(graph, shape, init, Type::float32, fixed) {}

ParamNode::ParamNode(Ptr<ExpressionGraph> graph,
                     const Shape& shape,
                     const Ptr<inits::NodeInitializer>& init,
                     const Type& valueType,
                     bool fixed)
    : Node(graph, shape, valueType),
      init_(init),
      initialized_(false) {
  init_->setAllocator(graph->allocator());
  setTrainable(!fixed);
  setMemoize(graph->isInference());
}

void ParamNode::init() {
  if(!initialized_) {
    init_->apply(val_);
    initialized_ = true;
  }
  init_.reset();
}
}  // namespace marian
<|endoftext|>


<commit_before>/*******************************************************************************
*    ALMA - Atacama Large Millimiter Array
*    (c) Associated Universities Inc., 2002 *
*    (c) European Southern Observatory, 2002
*    Copyright by ESO (in the framework of the ALMA collaboration)
*    and Cosylab 2002, All rights reserved
*
*    This library is free software; you can redistribute it and/or
*    modify it under the terms of the GNU Lesser General Public
*    License as published by the Free Software Foundation; either
*    version 2.1 of the License, or (at your option) any later version.
*
*    This library is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
*    Lesser General Public License for more details.
*
*    You should have received a copy of the GNU Lesser General Public
*    License along with this library; if not, write to the Free Software
*    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
*
*
*
* "@(#) $Id: contLogTestImpl.cpp,v 1.7 2007/12/28 04:13:32 cparedes Exp $"
*
* who       when        what
* --------  ----------  ----------------------------------------------
* eallaert  2007-11-05  initial version
*
*/

#include <contLogTestImpl.h>
#include <ACSErrTypeCommon.h>
#include <loggingLogLevelDefinition.h>
#include <loggingLogger.h>
#include "loggingGetLogger.h"
#include <iostream>

ACE_RCSID(contLogTest, contLogTestImpl, "$Id: contLogTestImpl.cpp,v 1.7 2007/12/28 04:13:32 cparedes Exp $")

/* ----------------------------------------------------------------*/
TestLogLevelsComp::TestLogLevelsComp(
		       const ACE_CString &name,
		       maci::ContainerServices * containerServices) :
    ACSComponentImpl(name, containerServices)
{
    // ACS_TRACE is used for debugging purposes
    ACS_TRACE("::TestLogLevelsComp::TestLogLevelsComp");
}
/* ----------------------------------------------------------------*/
TestLogLevelsComp::~TestLogLevelsComp()
{
    // ACS_TRACE is used for debugging purposes
    ACS_TRACE("::TestLogLevelsComp::~TestLogLevelsComp");
    ACS_DEBUG_PARAM("::TestLogLevelsComp::~TestLogLevelsComp", "Destroying %s...", name());
}
/* --------------------- [ CORBA interface ] ----------------------*/
::contLogTest::LongSeq*
TestLogLevelsComp::getLevels ()
    throw (CORBA::SystemException, ACSErrTypeCommon::CouldntPerformActionEx)
{
    Logging::Logger *l = getLogger();
    ::contLogTest::LongSeq_var level = new ::contLogTest::LongSeq(5);
	level->length(5);

    // need the equivalent of Java's logConfig.getMinLogLevel() etc. in C++
    for (int i = 0; i <5 ; i++)
    	level[i] = static_cast< CORBA::Long >(i);

    level[3] = static_cast< CORBA::Long >(l->getRemoteLevel());
    level[4] = static_cast< CORBA::Long >(l->getLocalLevel());
    return level._retn();
}

void
TestLogLevelsComp::logDummyMessages (const ::contLogTest::LongSeq & levels)
{
	ACE_Log_Priority p;
	CORBA::ULong t=0;
	for (t=0; t<levels.length(); t++){
		p = LogLevelDefinition::getACELogPriority(levels[t]);
		LogLevelDefinition lld = LogLevelDefinition::fromInteger(levels[t]);
		ACS_SHORT_LOG((p, "dummy log message for core level %d/%s", lld.getValue(), lld.getName().c_str()));
	}
	ACS_SHORT_LOG((p, "===last log messsage===", levels[t]));

}

/* --------------- [ MACI DLL support functions ] -----------------*/
#include <maciACSComponentDefines.h>
MACI_DLL_SUPPORT_FUNCTIONS(TestLogLevelsComp)
/* ----------------------------------------------------------------*/

/*___oOo___*/

<commit_msg>In method logDummyMessages(), log last message always at highest non-OFF level (so it always gets through, unless the central log level is put to OFF).<commit_after>/*******************************************************************************
*    ALMA - Atacama Large Millimiter Array
*    (c) Associated Universities Inc., 2002 *
*    (c) European Southern Observatory, 2002
*    Copyright by ESO (in the framework of the ALMA collaboration)
*    and Cosylab 2002, All rights reserved
*
*    This library is free software; you can redistribute it and/or
*    modify it under the terms of the GNU Lesser General Public
*    License as published by the Free Software Foundation; either
*    version 2.1 of the License, or (at your option) any later version.
*
*    This library is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
*    Lesser General Public License for more details.
*
*    You should have received a copy of the GNU Lesser General Public
*    License along with this library; if not, write to the Free Software
*    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
*
*
*
* "@(#) $Id: contLogTestImpl.cpp,v 1.8 2008/01/09 10:11:38 eallaert Exp $"
*
* who       when        what
* --------  ----------  ----------------------------------------------
* eallaert  2007-11-05  initial version
*
*/

#include <contLogTestImpl.h>
#include <ACSErrTypeCommon.h>
#include <loggingLogLevelDefinition.h>
#include <loggingLogger.h>
#include "loggingGetLogger.h"
#include <iostream>

ACE_RCSID(contLogTest, contLogTestImpl, "$Id: contLogTestImpl.cpp,v 1.8 2008/01/09 10:11:38 eallaert Exp $")

/* ----------------------------------------------------------------*/
TestLogLevelsComp::TestLogLevelsComp(
		       const ACE_CString &name,
		       maci::ContainerServices * containerServices) :
    ACSComponentImpl(name, containerServices)
{
    // ACS_TRACE is used for debugging purposes
    ACS_TRACE("::TestLogLevelsComp::TestLogLevelsComp");
}
/* ----------------------------------------------------------------*/
TestLogLevelsComp::~TestLogLevelsComp()
{
    // ACS_TRACE is used for debugging purposes
    ACS_TRACE("::TestLogLevelsComp::~TestLogLevelsComp");
    ACS_DEBUG_PARAM("::TestLogLevelsComp::~TestLogLevelsComp", "Destroying %s...", name());
}
/* --------------------- [ CORBA interface ] ----------------------*/
::contLogTest::LongSeq*
TestLogLevelsComp::getLevels ()
    throw (CORBA::SystemException, ACSErrTypeCommon::CouldntPerformActionEx)
{
    Logging::Logger *l = getLogger();
    ::contLogTest::LongSeq_var level = new ::contLogTest::LongSeq(5);
	level->length(5);

    // need the equivalent of Java's logConfig.getMinLogLevel() etc. in C++
    for (int i = 0; i <5 ; i++)
    	level[i] = static_cast< CORBA::Long >(i);

    level[3] = static_cast< CORBA::Long >(l->getRemoteLevel());
    level[4] = static_cast< CORBA::Long >(l->getLocalLevel());
    return level._retn();
}

void
TestLogLevelsComp::logDummyMessages (const ::contLogTest::LongSeq & levels)
{
	ACE_Log_Priority p;
	CORBA::ULong t=0;
	for (t=0; t<levels.length(); t++){
		p = LogLevelDefinition::getACELogPriority(levels[t]);
		LogLevelDefinition lld = LogLevelDefinition::fromInteger(levels[t]);
		ACS_SHORT_LOG((p, "dummy log message for core level %d/%s", lld.getValue(), lld.getName().c_str()));
	}
	// log last message always at highest, non-OFF level (so it should get always through,
	// unless the central level is put to OFF).
	p = LogLevelDefinition::getACELogPriority(levels[levels.length()-2]);
	ACS_SHORT_LOG((p, "===last log messsage==="));

}

/* --------------- [ MACI DLL support functions ] -----------------*/
#include <maciACSComponentDefines.h>
MACI_DLL_SUPPORT_FUNCTIONS(TestLogLevelsComp)
/* ----------------------------------------------------------------*/

/*___oOo___*/

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: FieldControls.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: oj $ $Date: 2001-03-14 10:35:10 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the License); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an AS IS basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef DBAUI_FIELDCONTROLS_HXX
#define DBAUI_FIELDCONTROLS_HXX

#ifndef _SV_FIELD_HXX
#include <vcl/field.hxx>
#endif
#ifndef _SV_LSTBOX_HXX
#include <vcl/lstbox.hxx>
#endif
#ifndef _DBAUI_MODULE_DBU_HXX_
#include "moduledbu.hxx"
#endif
#ifndef _SV_SVAPP_HXX
#include <vcl/svapp.hxx>
#endif
#ifndef DBAUI_SQLNAMEEDIT_HXX
#include "SqlNameEdit.hxx"
#endif

namespace dbaui
{
    class OSpecialReadOnly
    {
    protected:
        void SetSpecialReadOnly(BOOL _bReadOnly,Window *pWin)
        {
            StyleSettings aSystemStyle = Application::GetSettings().GetStyleSettings();
            const Color& rNewColor = _bReadOnly ? aSystemStyle.GetDialogColor() : aSystemStyle.GetFieldColor();
            pWin->SetBackground(Wallpaper(rNewColor));
            pWin->SetControlBackground(rNewColor);
        }
    public:
        virtual void SetSpecialReadOnly(BOOL _bReadOnly) = 0;
    };
    //==================================================================
    class OPropColumnEditCtrl : public OSQLNameEdit
                                ,public OSpecialReadOnly
    {
        short   m_nPos;
        String  m_strHelpText;
    public:
        inline OPropColumnEditCtrl(Window* pParent, ::rtl::OUString& _rAllowedChars, INT32 nHelpId, short nPosition = -1, WinBits nWinStyle = 0);

        inline BOOL IsModified() { return GetText() != GetSavedValue(); }

        short GetPos() const { return m_nPos; }
        String GetHelp() const { return m_strHelpText; }

        virtual void SetSpecialReadOnly(BOOL _bReadOnly)
        {
            SetReadOnly(_bReadOnly);
            OSpecialReadOnly::SetSpecialReadOnly(_bReadOnly,this);
        }
    };
    inline OPropColumnEditCtrl::OPropColumnEditCtrl(Window* pParent,
                                                    ::rtl::OUString& _rAllowedChars,
                                                    INT32 nHelpId,
                                                    short nPosition,
                                                    WinBits nWinStyle)
        :OSQLNameEdit(pParent, _rAllowedChars,nWinStyle)
        ,m_nPos(nPosition)
    {
        m_strHelpText = String(ModuleRes(nHelpId));
    }
    //==================================================================
    class OPropEditCtrl :   public Edit
                            ,public OSpecialReadOnly
    {
        short   m_nPos;
        String  m_strHelpText;

    public:
        inline OPropEditCtrl(Window* pParent, INT32 nHelpId, short nPosition = -1, WinBits nWinStyle = 0);

        inline BOOL IsModified() { return GetText() != GetSavedValue(); }

        short GetPos() const { return m_nPos; }
        String GetHelp() const { return m_strHelpText; }

        virtual void SetSpecialReadOnly(BOOL _bReadOnly)
        {
            SetReadOnly(_bReadOnly);
            OSpecialReadOnly::SetSpecialReadOnly(_bReadOnly,this);
        }
    };

    inline OPropEditCtrl::OPropEditCtrl(Window* pParent, INT32 nHelpId, short nPosition, WinBits nWinStyle)
        :Edit(pParent, nWinStyle)
        ,m_nPos(nPosition)
    {
        m_strHelpText = String(ModuleRes(nHelpId));
    }

    //==================================================================
    class OPropNumericEditCtrl : public NumericField
                                ,public OSpecialReadOnly
    {
        short   m_nPos;
        String  m_strHelpText;

    public:
        inline OPropNumericEditCtrl(Window* pParent, INT32 nHelpId, short nPosition = -1, WinBits nWinStyle = 0);

        inline BOOL IsModified() { return GetText() != GetSavedValue(); }

        short GetPos() const { return m_nPos; }
        String GetHelp() const { return m_strHelpText; }

        virtual void SetSpecialReadOnly(BOOL _bReadOnly)
        {
            SetReadOnly(_bReadOnly);
            OSpecialReadOnly::SetSpecialReadOnly(_bReadOnly,this);
        }
    };

    inline OPropNumericEditCtrl::OPropNumericEditCtrl(Window* pParent, INT32 nHelpId, short nPosition, WinBits nWinStyle)
        :NumericField(pParent, nWinStyle)
        ,m_nPos(nPosition)
    {
        m_strHelpText = String(ModuleRes(nHelpId));
    }

    //==================================================================
    class OPropListBoxCtrl : public ListBox
                            ,public OSpecialReadOnly
    {
        short   m_nPos;
        String  m_strHelpText;

    public:
        inline OPropListBoxCtrl(Window* pParent, INT32 nHelpId, short nPosition = -1, WinBits nWinStyle = 0);

        inline BOOL IsModified() { return GetSelectEntryPos() != GetSavedValue(); }

        short GetPos() const { return m_nPos; }
        String GetHelp() const { return m_strHelpText; }

        virtual void SetSpecialReadOnly(BOOL _bReadOnly)
        {
            SetReadOnly(_bReadOnly);
            OSpecialReadOnly::SetSpecialReadOnly(_bReadOnly,this);
        }
    };

    inline OPropListBoxCtrl::OPropListBoxCtrl(Window* pParent, INT32 nHelpId, short nPosition, WinBits nWinStyle)
        :ListBox(pParent, nWinStyle)
        ,m_nPos(nPosition)
    {
        m_strHelpText = String(ModuleRes(nHelpId));
    }
}
#endif // DBAUI_FIELDCONTROLS_HXX

<commit_msg>use USHORT instead of INT32<commit_after>/*************************************************************************
 *
 *  $RCSfile: FieldControls.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: oj $ $Date: 2001-03-19 12:40:59 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the License); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an AS IS basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef DBAUI_FIELDCONTROLS_HXX
#define DBAUI_FIELDCONTROLS_HXX

#ifndef _SV_FIELD_HXX
#include <vcl/field.hxx>
#endif
#ifndef _SV_LSTBOX_HXX
#include <vcl/lstbox.hxx>
#endif
#ifndef _DBAUI_MODULE_DBU_HXX_
#include "moduledbu.hxx"
#endif
#ifndef _SV_SVAPP_HXX
#include <vcl/svapp.hxx>
#endif
#ifndef DBAUI_SQLNAMEEDIT_HXX
#include "SqlNameEdit.hxx"
#endif

namespace dbaui
{
    class OSpecialReadOnly
    {
    protected:
        void SetSpecialReadOnly(BOOL _bReadOnly,Window *pWin)
        {
            StyleSettings aSystemStyle = Application::GetSettings().GetStyleSettings();
            const Color& rNewColor = _bReadOnly ? aSystemStyle.GetDialogColor() : aSystemStyle.GetFieldColor();
            pWin->SetBackground(Wallpaper(rNewColor));
            pWin->SetControlBackground(rNewColor);
        }
    public:
        virtual void SetSpecialReadOnly(BOOL _bReadOnly) = 0;
    };
    //==================================================================
    class OPropColumnEditCtrl : public OSQLNameEdit
                                ,public OSpecialReadOnly
    {
        short   m_nPos;
        String  m_strHelpText;
    public:
        inline OPropColumnEditCtrl(Window* pParent, ::rtl::OUString& _rAllowedChars, USHORT nHelpId, short nPosition = -1, WinBits nWinStyle = 0);

        inline BOOL IsModified() { return GetText() != GetSavedValue(); }

        short GetPos() const { return m_nPos; }
        String GetHelp() const { return m_strHelpText; }

        virtual void SetSpecialReadOnly(BOOL _bReadOnly)
        {
            SetReadOnly(_bReadOnly);
            OSpecialReadOnly::SetSpecialReadOnly(_bReadOnly,this);
        }
    };
    inline OPropColumnEditCtrl::OPropColumnEditCtrl(Window* pParent,
                                                    ::rtl::OUString& _rAllowedChars,
                                                    USHORT nHelpId,
                                                    short nPosition,
                                                    WinBits nWinStyle)
        :OSQLNameEdit(pParent, _rAllowedChars,nWinStyle)
        ,m_nPos(nPosition)
    {
        m_strHelpText = String(ModuleRes(nHelpId));
    }
    //==================================================================
    class OPropEditCtrl :   public Edit
                            ,public OSpecialReadOnly
    {
        short   m_nPos;
        String  m_strHelpText;

    public:
        inline OPropEditCtrl(Window* pParent, USHORT nHelpId, short nPosition = -1, WinBits nWinStyle = 0);
        inline OPropEditCtrl(Window* pParent, USHORT nHelpId, const ResId& _rRes,short nPosition = -1);

        inline BOOL IsModified() { return GetText() != GetSavedValue(); }

        short GetPos() const { return m_nPos; }
        String GetHelp() const { return m_strHelpText; }

        virtual void SetSpecialReadOnly(BOOL _bReadOnly)
        {
            SetReadOnly(_bReadOnly);
            OSpecialReadOnly::SetSpecialReadOnly(_bReadOnly,this);
        }
    };

    inline OPropEditCtrl::OPropEditCtrl(Window* pParent, USHORT nHelpId, short nPosition, WinBits nWinStyle)
        :Edit(pParent, nWinStyle)
        ,m_nPos(nPosition)
    {
        m_strHelpText = String(ModuleRes(nHelpId));
    }
    inline OPropEditCtrl::OPropEditCtrl(Window* pParent, USHORT nHelpId, const ResId& _rRes,short nPosition)
        :Edit(pParent, _rRes)
        ,m_nPos(nPosition)
    {
        m_strHelpText = String(ModuleRes(nHelpId));
    }

    //==================================================================
    class OPropNumericEditCtrl : public NumericField
                                ,public OSpecialReadOnly
    {
        short   m_nPos;
        String  m_strHelpText;

    public:
        inline OPropNumericEditCtrl(Window* pParent, USHORT nHelpId, short nPosition = -1, WinBits nWinStyle = 0);
        inline OPropNumericEditCtrl(Window* pParent, USHORT nHelpId, const ResId& _rRes,short nPosition = -1);

        inline BOOL IsModified() { return GetText() != GetSavedValue(); }

        short GetPos() const { return m_nPos; }
        String GetHelp() const { return m_strHelpText; }

        virtual void SetSpecialReadOnly(BOOL _bReadOnly)
        {
            SetReadOnly(_bReadOnly);
            OSpecialReadOnly::SetSpecialReadOnly(_bReadOnly,this);
        }
    };

    inline OPropNumericEditCtrl::OPropNumericEditCtrl(Window* pParent, USHORT nHelpId, short nPosition, WinBits nWinStyle)
        :NumericField(pParent, nWinStyle)
        ,m_nPos(nPosition)
    {
        m_strHelpText = String(ModuleRes(nHelpId));
    }
    inline OPropNumericEditCtrl::OPropNumericEditCtrl(Window* pParent, USHORT nHelpId, const ResId& _rRes,short nPosition)
        :NumericField(pParent, _rRes)
        ,m_nPos(nPosition)
    {
        m_strHelpText = String(ModuleRes(nHelpId));
    }

    //==================================================================
    class OPropListBoxCtrl : public ListBox
                            ,public OSpecialReadOnly
    {
        short   m_nPos;
        String  m_strHelpText;

    public:
        inline OPropListBoxCtrl(Window* pParent, USHORT nHelpId, short nPosition = -1, WinBits nWinStyle = 0);
        inline OPropListBoxCtrl(Window* pParent, USHORT nHelpId, const ResId& _rRes,short nPosition = -1);

        inline BOOL IsModified() { return GetSelectEntryPos() != GetSavedValue(); }

        short GetPos() const { return m_nPos; }
        String GetHelp() const { return m_strHelpText; }

        virtual void SetSpecialReadOnly(BOOL _bReadOnly)
        {
            SetReadOnly(_bReadOnly);
            OSpecialReadOnly::SetSpecialReadOnly(_bReadOnly,this);
        }
    };

    inline OPropListBoxCtrl::OPropListBoxCtrl(Window* pParent, USHORT nHelpId, short nPosition, WinBits nWinStyle)
        :ListBox(pParent, nWinStyle)
        ,m_nPos(nPosition)
    {
        m_strHelpText = String(ModuleRes(nHelpId));
    }
    inline OPropListBoxCtrl::OPropListBoxCtrl(Window* pParent, USHORT nHelpId, const ResId& _rRes,short nPosition)
        :ListBox(pParent, _rRes)
        ,m_nPos(nPosition)
    {
        m_strHelpText = String(ModuleRes(nHelpId));
    }
}
#endif // DBAUI_FIELDCONTROLS_HXX

<|endoftext|>


<commit_before>//----------------------------  thread_management.cc  ---------------------------
//    $Id$
//    Version: $Name$
//
//    Copyright (C) 2000, 2001, 2002, 2003 by the deal.II authors
//
//    This file is subject to QPL and may not be  distributed
//    without copyright and license information. Please refer
//    to the file deal.II/doc/license.html for the  text  and
//    further information on this license.
//
//----------------------------  thread_management.cc  ---------------------------

#include <base/thread_management.h>
#include <iostream>
#ifdef DEAL_II_USE_MT_POSIX
#  include <list>
#endif

#ifndef DEAL_II_USE_DIRECT_ERRNO_H
#  include <errno.h>
#else
#  include </usr/include/errno.h>
#endif
#include <sys/errno.h>

namespace Threads
{
                                   // counter and access mutex for the
                                   // number of threads
  volatile unsigned int n_existing_threads_counter = 1;
  ThreadMutex  n_existing_threads_mutex;

  void register_new_thread ()
  {
    n_existing_threads_mutex.acquire ();
    ++n_existing_threads_counter;
    n_existing_threads_mutex.release ();
  }

  void deregister_new_thread ()
  {
    n_existing_threads_mutex.acquire ();
    --n_existing_threads_counter;
    Assert (n_existing_threads_counter >= 1,
            ExcInternalError());
    n_existing_threads_mutex.release ();
  }

  void handle_std_exception (const std::exception &exc)
  {
    std::cerr << std::endl << std::endl
              << "---------------------------------------------------------"
              << std::endl
              << "In one of the sub-threads of this program, an exception\n"
              << "was thrown and not caught. Since exceptions do not\n"
              << "propagate to the main thread, the library has caught it.\n"
              << "The information carried by this exception is given below.\n"
              << std::endl
              << "---------------------------------------------------------"
              << std::endl;
    std::cerr << "Exception on processing: " << std::endl
              << exc.what() << std::endl
              << "Aborting!" << std::endl
              << "---------------------------------------------------------"
              << std::endl;
    std::abort ();
  }

  void handle_unknown_exception ()
  {
    std::cerr << std::endl << std::endl
              << "---------------------------------------------------------"
              << std::endl
              << "In one of the sub-threads of this program, an exception\n"
              << "was thrown and not caught. Since exceptions do not\n"
              << "propagate to the main thread, the library has caught it.\n"
              << "The information carried by this exception is given below.\n"
              << std::endl
              << "---------------------------------------------------------"
              << std::endl;
    std::cerr << "Type of exception is unknown, but not std::exception.\n"
              << "No additional information is available.\n"
              << "---------------------------------------------------------"
              << std::endl;
    std::abort ();
  }

  unsigned int n_existing_threads ()
  {
    n_existing_threads_mutex.acquire ();
    const unsigned int n = n_existing_threads_counter;
    n_existing_threads_mutex.release ();
    return n;
  }

#if DEAL_II_USE_MT != 1
  void DummyThreadManager::spawn (const FunPtr fun_ptr,
				  void *       fun_data,
				  int          /*flags*/) const
  {
    (*fun_ptr) (fun_data);
  }

  DummyBarrier::DummyBarrier (const unsigned int  count,
			      const char         *,
			      void               *)
  {
    Assert (count == 1, ExcBarrierSizeNotUseful(count));
  }

#else
#  ifdef DEAL_II_USE_MT_POSIX

  PosixThreadMutex::PosixThreadMutex ()
  {
    pthread_mutex_init (&mutex, 0);
  }

  PosixThreadMutex::~PosixThreadMutex ()
  {
    pthread_mutex_destroy (&mutex);
  }

  PosixThreadCondition::PosixThreadCondition ()
  {
    pthread_cond_init (&cond, 0);
  }

  PosixThreadCondition::~PosixThreadCondition ()
  {
    pthread_cond_destroy (&cond);
  }

#ifndef DEAL_II_USE_MT_POSIX_NO_BARRIERS
  PosixThreadBarrier::PosixThreadBarrier (const unsigned int  count,
					  const char         *,
					  void               *)
  {
    pthread_barrier_init (&barrier, 0, count);
  }

#else

  PosixThreadBarrier::PosixThreadBarrier (const unsigned int  count,
					  const char         *,
					  void               *)
                  : count (count)
  {
                                     // throw an exception unless we
                                     // have the special case that a
                                     // count of 1 is given, since
                                     // then waiting for a barrier is
                                     // a no-op, and we don't need the
                                     // POSIX functionality
    AssertThrow (count == 1,
		 ExcMessage ("Your local POSIX installation does not support\n"
			     "POSIX barriers. You will not be able to use\n"
			     "this class, but the rest of the threading\n"
			     "functionality is available."));
  }
#endif

  PosixThreadBarrier::~PosixThreadBarrier ()
  {
#ifndef DEAL_II_USE_MT_POSIX_NO_BARRIERS
    pthread_barrier_destroy (&barrier);
#else
                                     // unless the barrier is a no-op,
                                     // complain again (how did we get
                                     // here then?)
    if (count != 1)
      std::abort ();
#endif
  }

  int
  PosixThreadBarrier::wait ()
  {
#ifndef DEAL_II_USE_MT_POSIX_NO_BARRIERS
    return pthread_barrier_wait (&barrier);
#else
                                     // in the special case, this
                                     // function is a no-op. otherwise
                                     // complain about the missing
                                     // POSIX functions
    if (count == 1)
      return 0;
    else
      {
        std::abort ();
        return 1;
      };
#endif
  }

  PosixThreadManager::PosixThreadManager ()
		  :
		  thread_id_list (new std::list<pthread_t>())
  {}

  PosixThreadManager::~PosixThreadManager ()
  {
				     // wait for all threads, and
				     // release memory
    wait ();
    list_mutex.acquire ();
    if (thread_id_list != 0)
      delete reinterpret_cast<std::list<pthread_t>*>(thread_id_list);
    thread_id_list = 0;
    list_mutex.release ();
  }

  void
  PosixThreadManager::spawn (const FunPtr fun_ptr,
			     void *       fun_data,
			     int)
  {
    std::list<pthread_t> &tid_list
      = *reinterpret_cast<std::list<pthread_t>*>(thread_id_list);

    list_mutex.acquire ();
    tid_list.push_back (pthread_t());
    pthread_t *tid = &tid_list.back();
    list_mutex.release ();

                                     // start new thread. retry until
                                     // we either succeed or get an
                                     // error other than EAGAIN
    int error = 0;
    do
      {
	error = pthread_create (tid, 0, fun_ptr, fun_data);
      }
    while (error == EAGAIN);

    AssertThrow (error == 0, ExcInternalError());
  }

  void
  PosixThreadManager::wait () const
  {
    list_mutex.acquire ();
    std::list<pthread_t> &tid_list
      = *reinterpret_cast<std::list<pthread_t>*>(thread_id_list);

				     // wait for all the threads in
				     // turn
    for (std::list<pthread_t>::iterator i=tid_list.begin();
	 i != tid_list.end(); ++i)
      pthread_join (*i, 0);

				     // now we know that these threads
				     // have finished, remove their
				     // tid's from the list. this way,
				     // when new threads are spawned
				     // and waited for, we won't wait
				     // for expired threads with their
				     // invalid handles again
    tid_list.clear ();

    list_mutex.release ();
  }

#  endif
#endif

  FunDataCounter::FunDataCounter () :
		  n_fun_encapsulation_objects (0),
		  n_fun_data_base_objects (0)
  {}

  FunDataCounter::~FunDataCounter ()
  {
    AssertThrow (n_fun_encapsulation_objects == 0,
		 ExcObjectsExist("FunEncapsulation", n_fun_encapsulation_objects));
    AssertThrow (n_fun_data_base_objects == 0,
		 ExcObjectsExist("FunDataBase", n_fun_data_base_objects));
  }

/**
 * This is the global object which we will use to count the number of
 * threads generated, and which is used to complain when there is a
 * memory leak.
 */
  FunDataCounter fun_data_counter;

  FunEncapsulation::FunEncapsulation () :
		  fun_data_base (0)
  {
				     // keep some statistics on the
				     // number of variables around
    ++fun_data_counter.n_fun_encapsulation_objects;
  }

  FunEncapsulation::FunEncapsulation (FunDataBase *fun_data_base) :
		  fun_data_base (fun_data_base)
  {
				     // keep some statistics on the
				     // number of variables around
    ++fun_data_counter.n_fun_encapsulation_objects;
  }

  FunEncapsulation::FunEncapsulation (const FunEncapsulation &fun_data) :
		  fun_data_base (fun_data.fun_data_base->clone ())
  {
				     // keep some statistics on the
				     // number of variables around
    ++fun_data_counter.n_fun_encapsulation_objects;
  }

  FunEncapsulation::~FunEncapsulation ()
  {
                                     // note that the spawn() function
                                     // makes sure that we only get
                                     // here if the data has already
                                     // been copied by the spawned
                                     // thread, so destruction is safe
                                     // here.
                                     //
                                     // so do so.
    delete fun_data_base;
    fun_data_base = 0;

				   // keep some statistics on the
				   // number of variables around
    --fun_data_counter.n_fun_encapsulation_objects;
  }

  const FunEncapsulation &
  FunEncapsulation::operator = (const FunEncapsulation &/*fun_data*/)
  {
				     // this is not implemented at
				     // present. return dummy value
				     // instead
    Assert (false, ExcNotImplemented());
    const FunEncapsulation * const p = 0;
    return *p;
  }

  FunDataBase::FunDataBase (const ThreadEntryPoint thread_entry_point) :
		  thread_entry_point (thread_entry_point)
  {
				     // keep some statistics on the
				     // number of variables around
    ++fun_data_counter.n_fun_data_base_objects;
  }

  FunDataBase::FunDataBase (const FunDataBase &fun_data_base) :
		  thread_entry_point (fun_data_base.thread_entry_point)
  {
				     // keep some statistics on the
				     // number of variables around
    ++fun_data_counter.n_fun_data_base_objects;
  }

  FunDataBase::~FunDataBase ()
  {
				     // invalidate pointer for security
				     // reasons. accesses to this
				     // pointer after lifetime of this
				     // object will then fail
    thread_entry_point = 0;

				     // keep some statistics on the
				     // number of variables around
    --fun_data_counter.n_fun_data_base_objects;
  }

  void spawn (ThreadManager          &thread_manager,
	      const FunEncapsulation &fun_data)
  {
				     // lock the @p{fun_data_base} object
				     // to avoid destruction while its
				     // data is still accessed. the lock
				     // is released by the new thread
				     // once it has copied all data
    fun_data.fun_data_base->lock.acquire ();
				     // now start the new thread
#if DEAL_II_USE_MT == 1
#  if defined(DEAL_II_USE_MT_POSIX)
    thread_manager.spawn (*fun_data.fun_data_base->thread_entry_point,
			  (void*)&fun_data,
			  0);
#  else
#    error Not implemented
#  endif
#else
                                     // if not in MT mode, then simply
                                     // call the respective
                                     // serializing function, that
                                     // executes the given function
                                     // and return
    thread_manager.spawn (*fun_data.fun_data_base->thread_entry_point,
			  (void*)&fun_data,
			  0);
#endif

                                     // unlock the mutex and wait for
                                     // the condition that the data
                                     // has been copied to be
                                     // signalled. unlocking the mutex
                                     // will allow the other thread to
                                     // proceed to the signal() call,
                                     // which we want to catch here
                                     //
                                     // the mutex will subsequently be
                                     // locked again, but since we
                                     // don't need it any more, we can
                                     // go on unlocking it immediately
                                     // again
    fun_data.fun_data_base->condition.wait(fun_data.fun_data_base->lock);
    fun_data.fun_data_base->lock.release ();
  }

  void spawn_n (ThreadManager          &thread_manager,
		const FunEncapsulation &fun_data,
		const unsigned int      n_threads)
  {
    for (unsigned int i=0; i<n_threads; ++i)
      spawn (thread_manager, fun_data);
  }

  std::vector<std::pair<unsigned int,unsigned int> >
  split_interval (const unsigned int begin,
		  const unsigned int end,
		  const unsigned int n_intervals)
  {
    Assert (end >= begin, ExcInternalError());

    const unsigned int n_elements              = end-begin;
    const unsigned int n_elements_per_interval = n_elements / n_intervals;
    const unsigned int residual                = n_elements % n_intervals;

    std::vector<std::pair<unsigned int,unsigned int> > return_values (n_intervals);

    return_values[0].first = begin;
    for (unsigned int i=0; i<n_intervals; ++i)
      {
	if (i != n_intervals-1)
	  {
	    return_values[i].second = (return_values[i].first
				       + n_elements_per_interval);
					     // distribute residual in
					     // division equally among
					     // the first few
					     // subintervals
	    if (i < residual)
	      ++return_values[i].second;
	    return_values[i+1].first = return_values[i].second;
	  }
	else
	  return_values[i].second = end;
      };
    return return_values;
  }

}   // end namespace Thread
<commit_msg>Fix one problem.<commit_after>//----------------------------  thread_management.cc  ---------------------------
//    $Id$
//    Version: $Name$
//
//    Copyright (C) 2000, 2001, 2002, 2003 by the deal.II authors
//
//    This file is subject to QPL and may not be  distributed
//    without copyright and license information. Please refer
//    to the file deal.II/doc/license.html for the  text  and
//    further information on this license.
//
//----------------------------  thread_management.cc  ---------------------------

#include <base/thread_management.h>
#include <iostream>
#ifdef DEAL_II_USE_MT_POSIX
#  include <list>
#endif

#ifndef DEAL_II_USE_DIRECT_ERRNO_H
#  include <errno.h>
#else
#  include </usr/include/errno.h>
#endif
#include <sys/errno.h>

namespace Threads
{
                                   // counter and access mutex for the
                                   // number of threads
  volatile unsigned int n_existing_threads_counter = 1;
  ThreadMutex  n_existing_threads_mutex;

  void register_new_thread ()
  {
    n_existing_threads_mutex.acquire ();
    ++n_existing_threads_counter;
    n_existing_threads_mutex.release ();
  }

  void deregister_new_thread ()
  {
    n_existing_threads_mutex.acquire ();
    --n_existing_threads_counter;
    Assert (n_existing_threads_counter >= 1,
            ExcInternalError());
    n_existing_threads_mutex.release ();
  }

  void handle_std_exception (const std::exception &exc)
  {
    std::cerr << std::endl << std::endl
              << "---------------------------------------------------------"
              << std::endl
              << "In one of the sub-threads of this program, an exception\n"
              << "was thrown and not caught. Since exceptions do not\n"
              << "propagate to the main thread, the library has caught it.\n"
              << "The information carried by this exception is given below.\n"
              << std::endl
              << "---------------------------------------------------------"
              << std::endl;
    std::cerr << "Exception on processing: " << std::endl
              << exc.what() << std::endl
              << "Aborting!" << std::endl
              << "---------------------------------------------------------"
              << std::endl;
    std::abort ();
  }

  void handle_unknown_exception ()
  {
    std::cerr << std::endl << std::endl
              << "---------------------------------------------------------"
              << std::endl
              << "In one of the sub-threads of this program, an exception\n"
              << "was thrown and not caught. Since exceptions do not\n"
              << "propagate to the main thread, the library has caught it.\n"
              << "The information carried by this exception is given below.\n"
              << std::endl
              << "---------------------------------------------------------"
              << std::endl;
    std::cerr << "Type of exception is unknown, but not std::exception.\n"
              << "No additional information is available.\n"
              << "---------------------------------------------------------"
              << std::endl;
    std::abort ();
  }

  unsigned int n_existing_threads ()
  {
    n_existing_threads_mutex.acquire ();
    const unsigned int n = n_existing_threads_counter;
    n_existing_threads_mutex.release ();
    return n;
  }

#if DEAL_II_USE_MT != 1
  void DummyThreadManager::spawn (const FunPtr fun_ptr,
				  void *       fun_data,
				  int          /*flags*/) const
  {
    (*fun_ptr) (fun_data);
  }

  DummyBarrier::DummyBarrier (const unsigned int  count,
			      const char         *,
			      void               *)
  {
    Assert (count == 1, ExcBarrierSizeNotUseful(count));
  }

#else
#  ifdef DEAL_II_USE_MT_POSIX

  PosixThreadMutex::PosixThreadMutex ()
  {
    pthread_mutex_init (&mutex, 0);
  }

  PosixThreadMutex::~PosixThreadMutex ()
  {
    pthread_mutex_destroy (&mutex);
  }

  PosixThreadCondition::PosixThreadCondition ()
  {
    pthread_cond_init (&cond, 0);
  }

  PosixThreadCondition::~PosixThreadCondition ()
  {
    pthread_cond_destroy (&cond);
  }

#ifndef DEAL_II_USE_MT_POSIX_NO_BARRIERS
  PosixThreadBarrier::PosixThreadBarrier (const unsigned int  count,
					  const char         *,
					  void               *)
  {
    pthread_barrier_init (&barrier, 0, count);
  }

#else

  PosixThreadBarrier::PosixThreadBarrier (const unsigned int  count,
					  const char         *,
					  void               *)
                  : count (count)
  {
                                     // throw an exception unless we
                                     // have the special case that a
                                     // count of 1 is given, since
                                     // then waiting for a barrier is
                                     // a no-op, and we don't need the
                                     // POSIX functionality
    AssertThrow (count == 1,
		 ExcMessage ("Your local POSIX installation does not support\n"
			     "POSIX barriers. You will not be able to use\n"
			     "this class, but the rest of the threading\n"
			     "functionality is available."));
  }
#endif

  PosixThreadBarrier::~PosixThreadBarrier ()
  {
#ifndef DEAL_II_USE_MT_POSIX_NO_BARRIERS
    pthread_barrier_destroy (&barrier);
#else
                                     // unless the barrier is a no-op,
                                     // complain again (how did we get
                                     // here then?)
    if (count != 1)
      std::abort ();
#endif
  }

  int
  PosixThreadBarrier::wait ()
  {
#ifndef DEAL_II_USE_MT_POSIX_NO_BARRIERS
    return pthread_barrier_wait (&barrier);
#else
                                     // in the special case, this
                                     // function is a no-op. otherwise
                                     // complain about the missing
                                     // POSIX functions
    if (count == 1)
      return 0;
    else
      {
        std::abort ();
        return 1;
      };
#endif
  }

  PosixThreadManager::PosixThreadManager ()
		  :
		  thread_id_list (new std::list<pthread_t>())
  {}

  PosixThreadManager::~PosixThreadManager ()
  {
				     // wait for all threads, and
				     // release memory
    wait ();
    list_mutex.acquire ();
    if (thread_id_list != 0)
      delete reinterpret_cast<std::list<pthread_t>*>(thread_id_list);
    list_mutex.release ();
  }

  void
  PosixThreadManager::spawn (const FunPtr fun_ptr,
			     void *       fun_data,
			     int)
  {
    std::list<pthread_t> &tid_list
      = *reinterpret_cast<std::list<pthread_t>*>(thread_id_list);

    list_mutex.acquire ();
    tid_list.push_back (pthread_t());
    pthread_t *tid = &tid_list.back();
    list_mutex.release ();

                                     // start new thread. retry until
                                     // we either succeed or get an
                                     // error other than EAGAIN
    int error = 0;
    do
      {
	error = pthread_create (tid, 0, fun_ptr, fun_data);
      }
    while (error == EAGAIN);

    AssertThrow (error == 0, ExcInternalError());
  }

  void
  PosixThreadManager::wait () const
  {
    list_mutex.acquire ();
    std::list<pthread_t> &tid_list
      = *reinterpret_cast<std::list<pthread_t>*>(thread_id_list);

				     // wait for all the threads in
				     // turn
    for (std::list<pthread_t>::iterator i=tid_list.begin();
	 i != tid_list.end(); ++i)
      pthread_join (*i, 0);

				     // now we know that these threads
				     // have finished, remove their
				     // tid's from the list. this way,
				     // when new threads are spawned
				     // and waited for, we won't wait
				     // for expired threads with their
				     // invalid handles again
    tid_list.clear ();

    list_mutex.release ();
  }

#  endif
#endif

  FunDataCounter::FunDataCounter () :
		  n_fun_encapsulation_objects (0),
		  n_fun_data_base_objects (0)
  {}

  FunDataCounter::~FunDataCounter ()
  {
    AssertThrow (n_fun_encapsulation_objects == 0,
		 ExcObjectsExist("FunEncapsulation", n_fun_encapsulation_objects));
    AssertThrow (n_fun_data_base_objects == 0,
		 ExcObjectsExist("FunDataBase", n_fun_data_base_objects));
  }

/**
 * This is the global object which we will use to count the number of
 * threads generated, and which is used to complain when there is a
 * memory leak.
 */
  FunDataCounter fun_data_counter;

  FunEncapsulation::FunEncapsulation () :
		  fun_data_base (0)
  {
				     // keep some statistics on the
				     // number of variables around
    ++fun_data_counter.n_fun_encapsulation_objects;
  }

  FunEncapsulation::FunEncapsulation (FunDataBase *fun_data_base) :
		  fun_data_base (fun_data_base)
  {
				     // keep some statistics on the
				     // number of variables around
    ++fun_data_counter.n_fun_encapsulation_objects;
  }

  FunEncapsulation::FunEncapsulation (const FunEncapsulation &fun_data) :
		  fun_data_base (fun_data.fun_data_base->clone ())
  {
				     // keep some statistics on the
				     // number of variables around
    ++fun_data_counter.n_fun_encapsulation_objects;
  }

  FunEncapsulation::~FunEncapsulation ()
  {
                                     // note that the spawn() function
                                     // makes sure that we only get
                                     // here if the data has already
                                     // been copied by the spawned
                                     // thread, so destruction is safe
                                     // here.
                                     //
                                     // so do so.
    delete fun_data_base;
    fun_data_base = 0;

				   // keep some statistics on the
				   // number of variables around
    --fun_data_counter.n_fun_encapsulation_objects;
  }

  const FunEncapsulation &
  FunEncapsulation::operator = (const FunEncapsulation &/*fun_data*/)
  {
				     // this is not implemented at
				     // present. return dummy value
				     // instead
    Assert (false, ExcNotImplemented());
    const FunEncapsulation * const p = 0;
    return *p;
  }

  FunDataBase::FunDataBase (const ThreadEntryPoint thread_entry_point) :
		  thread_entry_point (thread_entry_point)
  {
				     // keep some statistics on the
				     // number of variables around
    ++fun_data_counter.n_fun_data_base_objects;
  }

  FunDataBase::FunDataBase (const FunDataBase &fun_data_base) :
		  thread_entry_point (fun_data_base.thread_entry_point)
  {
				     // keep some statistics on the
				     // number of variables around
    ++fun_data_counter.n_fun_data_base_objects;
  }

  FunDataBase::~FunDataBase ()
  {
				     // invalidate pointer for security
				     // reasons. accesses to this
				     // pointer after lifetime of this
				     // object will then fail
    thread_entry_point = 0;

				     // keep some statistics on the
				     // number of variables around
    --fun_data_counter.n_fun_data_base_objects;
  }

  void spawn (ThreadManager          &thread_manager,
	      const FunEncapsulation &fun_data)
  {
				     // lock the @p{fun_data_base} object
				     // to avoid destruction while its
				     // data is still accessed. the lock
				     // is released by the new thread
				     // once it has copied all data
    fun_data.fun_data_base->lock.acquire ();
				     // now start the new thread
#if DEAL_II_USE_MT == 1
#  if defined(DEAL_II_USE_MT_POSIX)
    thread_manager.spawn (*fun_data.fun_data_base->thread_entry_point,
			  (void*)&fun_data,
			  0);
#  else
#    error Not implemented
#  endif
#else
                                     // if not in MT mode, then simply
                                     // call the respective
                                     // serializing function, that
                                     // executes the given function
                                     // and return
    thread_manager.spawn (*fun_data.fun_data_base->thread_entry_point,
			  (void*)&fun_data,
			  0);
#endif

                                     // unlock the mutex and wait for
                                     // the condition that the data
                                     // has been copied to be
                                     // signalled. unlocking the mutex
                                     // will allow the other thread to
                                     // proceed to the signal() call,
                                     // which we want to catch here
                                     //
                                     // the mutex will subsequently be
                                     // locked again, but since we
                                     // don't need it any more, we can
                                     // go on unlocking it immediately
                                     // again
    fun_data.fun_data_base->condition.wait(fun_data.fun_data_base->lock);
    fun_data.fun_data_base->lock.release ();
  }

  void spawn_n (ThreadManager          &thread_manager,
		const FunEncapsulation &fun_data,
		const unsigned int      n_threads)
  {
    for (unsigned int i=0; i<n_threads; ++i)
      spawn (thread_manager, fun_data);
  }

  std::vector<std::pair<unsigned int,unsigned int> >
  split_interval (const unsigned int begin,
		  const unsigned int end,
		  const unsigned int n_intervals)
  {
    Assert (end >= begin, ExcInternalError());

    const unsigned int n_elements              = end-begin;
    const unsigned int n_elements_per_interval = n_elements / n_intervals;
    const unsigned int residual                = n_elements % n_intervals;

    std::vector<std::pair<unsigned int,unsigned int> > return_values (n_intervals);

    return_values[0].first = begin;
    for (unsigned int i=0; i<n_intervals; ++i)
      {
	if (i != n_intervals-1)
	  {
	    return_values[i].second = (return_values[i].first
				       + n_elements_per_interval);
					     // distribute residual in
					     // division equally among
					     // the first few
					     // subintervals
	    if (i < residual)
	      ++return_values[i].second;
	    return_values[i+1].first = return_values[i].second;
	  }
	else
	  return_values[i].second = end;
      };
    return return_values;
  }

}   // end namespace Thread
<|endoftext|>


<commit_before>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
#include <berryWorkbenchPlugin.h>
#include <berryIQtStyleManager.h>

// Qmitk
#include "ChartExample.h"

// Qt
#include <QMessageBox>
#include <QRandomGenerator>

// mitk image
#include <mitkImage.h>

const std::string ChartExample::VIEW_ID = "org.mitk.views.chartexample";

void ChartExample::SetFocus()
{
  m_Controls.m_buttonCreateChart->setFocus();
}

void ChartExample::CreateQtPartControl(QWidget *parent)
{
  // create GUI widgets from the Qt Designer's .ui file
  m_Controls.setupUi(parent);
  connect(m_Controls.m_buttonCreateChart, &QPushButton::clicked, this, &ChartExample::CreateChart);
  connect(m_Controls.m_buttonClearChart, &QPushButton::clicked, this, &ChartExample::ClearChart);
  connect(m_Controls.m_buttonAddData, &QPushButton::clicked, this, &ChartExample::AddData);

  FillRandomDataValues();

  m_Controls.m_Chart->SetTheme(GetColorTheme());

  m_Controls.m_lineEditXAxisLabel->setText("xLabel");
  m_Controls.m_lineEditYAxisLabel->setText("yLabel");

  m_chartNameToChartType.emplace("bar", QmitkChartWidget::ChartType::bar);
  m_chartNameToChartType.emplace("line", QmitkChartWidget::ChartType::line);
  m_chartNameToChartType.emplace("spline", QmitkChartWidget::ChartType::spline);
  m_chartNameToChartType.emplace("pie", QmitkChartWidget::ChartType::pie);
  m_chartNameToChartType.emplace("area", QmitkChartWidget::ChartType::area);
  m_chartNameToChartType.emplace("area-spline", QmitkChartWidget::ChartType::area_spline);
  m_chartNameToChartType.emplace("scatter", QmitkChartWidget::ChartType::scatter);

  m_LineNameToLineType.emplace("solid", QmitkChartWidget::LineStyle::solid);
  m_LineNameToLineType.emplace("dashed", QmitkChartWidget::LineStyle::dashed);

  m_AxisScaleNameToAxisScaleType.emplace("linear", QmitkChartWidget::AxisScale::linear);
  m_AxisScaleNameToAxisScaleType.emplace("logarithmic", QmitkChartWidget::AxisScale::log);
}

void ChartExample::FillRandomDataValues()
{
  std::vector<double> numbers = generateRandomNumbers(10, 10.0);
  std::string text = convertToText(numbers, ";");
  m_Controls.m_lineEditDataVector->setText(QString::fromStdString(text));

  m_Controls.m_lineEditDataLabel->setText("test" + QString::number(countForUID));
  countForUID++;
}

void ChartExample::CreateChart()
{
  auto dataYAxisScaleType = m_AxisScaleNameToAxisScaleType.at(m_Controls.m_comboBoxYAxisScale->currentText().toStdString());
  auto xAxisLabel = m_Controls.m_lineEditXAxisLabel->text().toStdString();
  auto yAxisLabel = m_Controls.m_lineEditYAxisLabel->text().toStdString();
  auto showLegend = m_Controls.m_checkBoxShowLegend->isChecked();
  auto showDataPoints = m_Controls.m_checkBoxShowDataPoints->isChecked();
  auto stackedData = m_Controls.m_checkBoxStackedData->isChecked();
  auto showSubchart = m_Controls.m_checkBoxShowSubchart->isChecked();

  m_Controls.m_Chart->SetYAxisScale(dataYAxisScaleType);
  m_Controls.m_Chart->SetXAxisLabel(xAxisLabel);
  m_Controls.m_Chart->SetYAxisLabel(yAxisLabel);
  m_Controls.m_Chart->SetShowLegend(showLegend);
  m_Controls.m_Chart->SetShowDataPoints(showDataPoints);
  m_Controls.m_Chart->SetStackedData(stackedData);
  m_Controls.m_Chart->Show(showSubchart);
}

void ChartExample::ClearChart()
{
  m_Controls.m_Chart->Clear();
  m_Controls.m_plainTextEditDataView->clear();
}

void ChartExample::AddData()
{
  auto lineEditData = m_Controls.m_lineEditDataVector->text();
  std::vector<double> data;
  for(const QString entry : lineEditData.split(';'))
  {
    data.push_back(entry.toDouble());
  }

  auto chartType = m_chartNameToChartType.at(m_Controls.m_comboBoxChartType->currentText().toStdString());
  std::string dataLabel = m_Controls.m_lineEditDataLabel->text().toStdString();
  std::string dataColor = m_Controls.m_lineEditColor->text().toStdString();
  auto dataLineStyleType = m_LineNameToLineType.at(m_Controls.m_comboBoxLineStyle->currentText().toStdString());

  m_Controls.m_Chart->AddData1D(data, dataLabel, chartType);
  if (!dataColor.empty()) {
    m_Controls.m_Chart->SetColor(dataLabel, dataColor);
  }
  m_Controls.m_Chart->SetLineStyle(dataLabel, dataLineStyleType);

  QString dataOverview;
  dataOverview.append(m_Controls.m_lineEditDataLabel->text());
  dataOverview.append("(").append(m_Controls.m_comboBoxChartType->currentText());
  if (!dataColor.empty()) {
    dataOverview.append(", ").append(dataColor.c_str());
  }
  dataOverview.append(", ").append(m_Controls.m_comboBoxLineStyle->currentText());
  dataOverview.append(")");
  dataOverview.append(":").append(lineEditData);

  m_Controls.m_plainTextEditDataView->appendPlainText(dataOverview);

  FillRandomDataValues();
}

std::vector<double> ChartExample::generateRandomNumbers(unsigned int amount, double max) const
{
  QRandomGenerator gen;
  gen.seed(time(NULL));

  std::vector<double> data;
  for (unsigned int i = 0; i < amount; i++) {
    data.push_back(gen.bounded(max));
  }

  return data;
}

std::string ChartExample::convertToText(std::vector<double> numbers, std::string delimiter) const
{
  std::ostringstream oss;
  oss.precision(3);

  if (!numbers.empty())
  {
    for (auto number : numbers) {
      oss << number << delimiter;
    }
  }
  auto aString = oss.str();
  aString.pop_back();
  return aString;
}

QmitkChartWidget::ChartStyle ChartExample::GetColorTheme() const
{
  ctkPluginContext* context = berry::WorkbenchPlugin::GetDefault()->GetPluginContext();
  ctkServiceReference styleManagerRef = context->getServiceReference<berry::IQtStyleManager>();
  if (styleManagerRef)
  {
    auto styleManager = context->getService<berry::IQtStyleManager>(styleManagerRef);
    if (styleManager->GetStyle().name == "Dark") {
      return QmitkChartWidget::ChartStyle::darkstyle;
    }
    else {
      return QmitkChartWidget::ChartStyle::lightstyle;
    }
  }
  return QmitkChartWidget::ChartStyle::darkstyle;
}

<commit_msg>removed unecessary include<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
#include <berryWorkbenchPlugin.h>
#include <berryIQtStyleManager.h>

// Qmitk
#include "ChartExample.h"

// Qt
#include <QMessageBox>
#include <QRandomGenerator>

const std::string ChartExample::VIEW_ID = "org.mitk.views.chartexample";

void ChartExample::SetFocus()
{
  m_Controls.m_buttonCreateChart->setFocus();
}

void ChartExample::CreateQtPartControl(QWidget *parent)
{
  // create GUI widgets from the Qt Designer's .ui file
  m_Controls.setupUi(parent);
  connect(m_Controls.m_buttonCreateChart, &QPushButton::clicked, this, &ChartExample::CreateChart);
  connect(m_Controls.m_buttonClearChart, &QPushButton::clicked, this, &ChartExample::ClearChart);
  connect(m_Controls.m_buttonAddData, &QPushButton::clicked, this, &ChartExample::AddData);

  FillRandomDataValues();

  m_Controls.m_Chart->SetTheme(GetColorTheme());

  m_Controls.m_lineEditXAxisLabel->setText("xLabel");
  m_Controls.m_lineEditYAxisLabel->setText("yLabel");

  m_chartNameToChartType.emplace("bar", QmitkChartWidget::ChartType::bar);
  m_chartNameToChartType.emplace("line", QmitkChartWidget::ChartType::line);
  m_chartNameToChartType.emplace("spline", QmitkChartWidget::ChartType::spline);
  m_chartNameToChartType.emplace("pie", QmitkChartWidget::ChartType::pie);
  m_chartNameToChartType.emplace("area", QmitkChartWidget::ChartType::area);
  m_chartNameToChartType.emplace("area-spline", QmitkChartWidget::ChartType::area_spline);
  m_chartNameToChartType.emplace("scatter", QmitkChartWidget::ChartType::scatter);

  m_LineNameToLineType.emplace("solid", QmitkChartWidget::LineStyle::solid);
  m_LineNameToLineType.emplace("dashed", QmitkChartWidget::LineStyle::dashed);

  m_AxisScaleNameToAxisScaleType.emplace("linear", QmitkChartWidget::AxisScale::linear);
  m_AxisScaleNameToAxisScaleType.emplace("logarithmic", QmitkChartWidget::AxisScale::log);
}

void ChartExample::FillRandomDataValues()
{
  std::vector<double> numbers = generateRandomNumbers(10, 10.0);
  std::string text = convertToText(numbers, ";");
  m_Controls.m_lineEditDataVector->setText(QString::fromStdString(text));

  m_Controls.m_lineEditDataLabel->setText("test" + QString::number(countForUID));
  countForUID++;
}

void ChartExample::CreateChart()
{
  auto dataYAxisScaleType = m_AxisScaleNameToAxisScaleType.at(m_Controls.m_comboBoxYAxisScale->currentText().toStdString());
  auto xAxisLabel = m_Controls.m_lineEditXAxisLabel->text().toStdString();
  auto yAxisLabel = m_Controls.m_lineEditYAxisLabel->text().toStdString();
  auto showLegend = m_Controls.m_checkBoxShowLegend->isChecked();
  auto showDataPoints = m_Controls.m_checkBoxShowDataPoints->isChecked();
  auto stackedData = m_Controls.m_checkBoxStackedData->isChecked();
  auto showSubchart = m_Controls.m_checkBoxShowSubchart->isChecked();

  m_Controls.m_Chart->SetYAxisScale(dataYAxisScaleType);
  m_Controls.m_Chart->SetXAxisLabel(xAxisLabel);
  m_Controls.m_Chart->SetYAxisLabel(yAxisLabel);
  m_Controls.m_Chart->SetShowLegend(showLegend);
  m_Controls.m_Chart->SetShowDataPoints(showDataPoints);
  m_Controls.m_Chart->SetStackedData(stackedData);
  m_Controls.m_Chart->Show(showSubchart);
}

void ChartExample::ClearChart()
{
  m_Controls.m_Chart->Clear();
  m_Controls.m_plainTextEditDataView->clear();
}

void ChartExample::AddData()
{
  auto lineEditData = m_Controls.m_lineEditDataVector->text();
  std::vector<double> data;
  for(const QString entry : lineEditData.split(';'))
  {
    data.push_back(entry.toDouble());
  }

  auto chartType = m_chartNameToChartType.at(m_Controls.m_comboBoxChartType->currentText().toStdString());
  std::string dataLabel = m_Controls.m_lineEditDataLabel->text().toStdString();
  std::string dataColor = m_Controls.m_lineEditColor->text().toStdString();
  auto dataLineStyleType = m_LineNameToLineType.at(m_Controls.m_comboBoxLineStyle->currentText().toStdString());

  m_Controls.m_Chart->AddData1D(data, dataLabel, chartType);
  if (!dataColor.empty()) {
    m_Controls.m_Chart->SetColor(dataLabel, dataColor);
  }
  m_Controls.m_Chart->SetLineStyle(dataLabel, dataLineStyleType);

  QString dataOverview;
  dataOverview.append(m_Controls.m_lineEditDataLabel->text());
  dataOverview.append("(").append(m_Controls.m_comboBoxChartType->currentText());
  if (!dataColor.empty()) {
    dataOverview.append(", ").append(dataColor.c_str());
  }
  dataOverview.append(", ").append(m_Controls.m_comboBoxLineStyle->currentText());
  dataOverview.append(")");
  dataOverview.append(":").append(lineEditData);

  m_Controls.m_plainTextEditDataView->appendPlainText(dataOverview);

  FillRandomDataValues();
}

std::vector<double> ChartExample::generateRandomNumbers(unsigned int amount, double max) const
{
  QRandomGenerator gen;
  gen.seed(time(NULL));

  std::vector<double> data;
  for (unsigned int i = 0; i < amount; i++) {
    data.push_back(gen.bounded(max));
  }

  return data;
}

std::string ChartExample::convertToText(std::vector<double> numbers, std::string delimiter) const
{
  std::ostringstream oss;
  oss.precision(3);

  if (!numbers.empty())
  {
    for (auto number : numbers) {
      oss << number << delimiter;
    }
  }
  auto aString = oss.str();
  aString.pop_back();
  return aString;
}

QmitkChartWidget::ChartStyle ChartExample::GetColorTheme() const
{
  ctkPluginContext* context = berry::WorkbenchPlugin::GetDefault()->GetPluginContext();
  ctkServiceReference styleManagerRef = context->getServiceReference<berry::IQtStyleManager>();
  if (styleManagerRef)
  {
    auto styleManager = context->getService<berry::IQtStyleManager>(styleManagerRef);
    if (styleManager->GetStyle().name == "Dark") {
      return QmitkChartWidget::ChartStyle::darkstyle;
    }
    else {
      return QmitkChartWidget::ChartStyle::lightstyle;
    }
  }
  return QmitkChartWidget::ChartStyle::darkstyle;
}

<|endoftext|>