<commit_before>// Copyright Hugh Perkins 2016

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "handle_branching.h"

#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/ValueSymbolTable.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/SourceMgr.h"
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <map>
#include <set>
#include <iostream>
#include <stdexcept>
#include <sstream>
#include <fstream>

#include <iostream>

using namespace std;
using namespace llvm;

namespace cocl {
    // a Block has one or more links to child blocks
    // a Block can be linked to by one or more blocks
    // we probably need a root block, which holds the others
    static int nextId = 0;

    class Block {
    public:
        int id;
        Block() {
            this->id = nextId;
            nextId++;
        }
        virtual string blockType() const {
            return "Block";
        }
        virtual void dump(set<const Block *> &seen, string indent = "") const = 0;
        vector<Block *>incoming;
    };
    class RootBlock : public Block {
    public:
        Block *first = 0;
        virtual string blockType() const {
            return "RootBlock";
        }
        virtual void dump(set<const Block *> &seen, string indent = "") const {
            seen.insert(this);
            cout << indent << "RootBlock " << this->id << endl;
            if(seen.find(first) == seen.end()) {
                first->dump(seen, indent + "  ");
            }
        }
    };
    class If : public Block {
    public:
        Value *condition = 0;
        Block *trueBlock = 0;
        Block *falseBlock = 0;
        virtual string blockType() const {
            return "If";
        }
        virtual void dump(set<const Block *> &seen, string indent) const {
            seen.insert(this);
            cout << indent << "If " << this->id << endl;
            cout << indent << "  True:" << endl;
            if(seen.find(trueBlock) == seen.end()) {
                trueBlock->dump(seen, indent + "    ");
            } else {
                cout << indent << "    (*" << trueBlock->id << endl;
            }
            if(falseBlock != 0) {
                cout << indent << "  False:" << endl;
                if(seen.find(falseBlock) == seen.end()) {
                    falseBlock->dump(seen, indent + "    ");
                } else {
                    cout << indent << "    (*" << falseBlock->id << endl;
                }
            }
        }
    };
    class ConditionalBranch : public Block {
    public:
        Value *condition = 0;
        Block *trueNext = 0;
        Block *falseNext = 0;
        virtual string blockType() const {
            return "ConditionalBranch";
        }
        virtual void dump(set<const Block *> &seen, string indent) const {
            seen.insert(this);
            cout << indent << "ConditionalBranch " << this->id << endl;
            cout << indent << "  True:" << endl;
            if(seen.find(trueNext) == seen.end()) {
                trueNext->dump(seen, indent + "    ");
            } else {
                cout << indent << "    (*" << trueNext->id << endl;
            }
            if(falseNext != 0) {
                cout << indent << "  False:" << endl;
                if(seen.find(falseNext) == seen.end()) {
                    falseNext->dump(seen, indent + "    ");
                } else {
                    cout << indent << "    (*" << falseNext->id << endl;
                }
            }
        }
    };
    class BasicBlockBlock : public Block {
    public:
        BasicBlock *basicBlock = 0;
        vector<Value *> instructions;
        Block *next; // initially will probalby point to a Branch block
        virtual string blockType() const {
            return "BasicBlockBlock";
        }
        virtual void dump(set<const Block *> &seen, string indent) const {
            seen.insert(this);
            cout << indent << "BasicBlockBlock " << this->id << endl;
            if(seen.find(next) == seen.end()) {
                next->dump(seen, indent);
            } else {
                cout << indent << "  (*" << next->id << endl;
            }
        }
    };
    class Sequence : public Block {
    public:
        vector<Block *> children;
        virtual string blockType() const {
            return "Sequence";
        }
        virtual void dump(set<const Block *> &seen, string indent) const {
            seen.insert(this);
            cout << indent << "Sequence " << this->id << endl;
            for(auto it = children.begin(); it != children.end(); it++) {
                Block *child = *it;
                if(seen.find(child) == seen.end()) {
                    child->dump(seen, indent + "  ");
                } else {
                    cout << indent << "  (*" << child->id << endl;
                }
            }
        }
    };
    class ReturnBlock : public Block {
    public:
        virtual string blockType() const {
            return "ReturnBlock";
        }
        virtual void dump(set<const Block *> &seen, string indent) const {
            cout << indent << "ReturnBlock " << this->id << endl;
        }
    };
    vector<unique_ptr<Block> > blocks; // doesnt include the root. I guess. ???
    map<BasicBlock *, Block *> blockByBasicBlock;

    // void dumpBlock(Block *block) {
    //     cout << "dumping block" << endl;
    //     block->dump();
    // }

    void mergeSequences(Block *root) {
        // basically we look for any block with one single incoming, and that incoming is a basicblockblock
        bool didAMerge = false;
        while(didAMerge) {
            for(auto it = blocks.begin(); it != blocks.end(); it++) {
                Block *block = it->get();
                if(block->incoming.size() == 1) {
                    cout << "block " << block->id << " has only one incoming" << endl;
                    Block *parent = block->incoming[0];
                    if(BasicBlockBlock *parentBlockBlock = dynamic_cast<BasicBlockBlock*>(parent)) {
                        cout << "its a blockblock" << endl;
                        if(BasicBlockBlock *thisBlockBlock = dynamic_cast<BasicBlockBlock*>(block)) {
                            // so merge...
                            unique_ptr<Sequence> sequence(new Sequence());
                            sequence->children.push_back(parent);
                            sequence->children.push_back(block);
                            for(auto parentincit = parent->incoming.begin(); parentincit != parent->incoming.end(); parentincit++) {
                                Block *parentinc = *parentincit;
                                sequence->incoming.push_back(parentinc);
                            }
                            parent->incoming.clear();
                            parent->incoming.push_back(sequence.get());
                            parentBlockBlock->next = 0;
                            block->incoming.clear();
                            block->incoming.push_back(sequence.get());
                            thisBlockBlock->next = 0;
                            blocks.push_back(std::move(sequence));
                            didAMerge = true;
                        }
                    } else {
                        cout << "but not a basicblockblock" << endl;
                    }
                }
            }
        }
    }

    void handle_branching_simplify(Function *F) {
        cout << "simplify " << string(F->getName()) << endl;
        unique_ptr<RootBlock> root(new RootBlock());
        for(auto it=F->begin(); it != F->end(); it++) {
            cout << "block" << endl;
            BasicBlock *basicBlock = &*it;
            unique_ptr<BasicBlockBlock> block(new BasicBlockBlock());
            block->basicBlock = basicBlock;
            for(auto instit=basicBlock->begin(); instit != basicBlock->end(); instit++) {
                Instruction *inst = &*instit;
                // skip branches, phis and so on, which we'll handle later, somehow...
                if(isa<BranchInst>(inst)) {
                    continue;
                }
                if(isa<PHINode>(inst)) {
                    continue;
                }
                if(isa<ReturnInst>(inst)) {
                    continue;
                }
                block->instructions.push_back(inst);
            }
            blockByBasicBlock[basicBlock] = block.get();
            blocks.push_back(std::move(block));
        }

        root->first = blockByBasicBlock[&F->getEntryBlock()];
        root->first->incoming.push_back(root.get());
        // go through, and start linking stuff togehter, now that we have a map from basic block to block
        for(auto it=F->begin(); it != F->end(); it++) {
            BasicBlock *basicBlock = &*it;
            BasicBlockBlock *block = dynamic_cast<BasicBlockBlock *>(blockByBasicBlock[basicBlock]);
            // I think that each block has to end initially either with a branch or a return?
            Instruction *lastInst = basicBlock->getTerminator();
            cout << "lastinst:" << endl;
            lastInst->dump();
            cout << endl;
            if(isa<ReturnInst>(lastInst)) {
                cout << "finishes in ret" << endl;
                unique_ptr<ReturnBlock> retBlock(new ReturnBlock());
                block->next = retBlock.get();
                block->next->incoming.push_back(block);
                blocks.push_back(std::move(retBlock));
            } else if(BranchInst* branchInst = dyn_cast<BranchInst>(lastInst)) {
                cout << "its a branch" << endl;
                // if its unconditional, we just link directly to the next block
                // otherwise we link to a ConditionalBranch block
                if(branchInst->isUnconditional()) {
                    cout << "unconditonal branch" << endl;
                    BasicBlock *next = branchInst->getSuccessor(0);
                    Block *nextBlock = blockByBasicBlock[next];
                    block->next = nextBlock;
                    block->next->incoming.push_back(block);
                } else {
                    // conditional
                    // create a ConditionalBranch block
                    cout << "conditonal branch" << endl;
                    unique_ptr<ConditionalBranch> conditionalBranch(new ConditionalBranch());
                    BasicBlock *trueBasicBlock = branchInst->getSuccessor(0);
                    Block *trueBlock = blockByBasicBlock[trueBasicBlock];
                    conditionalBranch->trueNext = trueBlock;
                    conditionalBranch->trueNext->incoming.push_back(conditionalBranch.get());
                    conditionalBranch->falseNext = 0;
                    if(branchInst->getNumSuccessors() == 2) {
                        BasicBlock *falseBasicBlock = branchInst->getSuccessor(1);
                        Block *falseBlock = blockByBasicBlock[falseBasicBlock];
                        conditionalBranch->falseNext = falseBlock;
                        conditionalBranch->falseNext->incoming.push_back(conditionalBranch.get());
                    }
                    block->next = conditionalBranch.get();
                    block->next->incoming.push_back(block);
                    blocks.push_back(std::move(conditionalBranch));
                }
            } else {
                cout << "hmmm, how did we get here???" << endl;
                cout << "lastinst:" << endl;
                lastInst->dump();
                cout << endl;
                throw runtime_error("dont know how we got here...");
            }
        }

        mergeSequences(root.get());

        set<const Block *>seen;
        root->dump(seen, "");
    }
}
<commit_msg>add sequence merge<commit_after>// Copyright Hugh Perkins 2016

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "handle_branching.h"

#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/ValueSymbolTable.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/SourceMgr.h"
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <map>
#include <set>
#include <iostream>
#include <stdexcept>
#include <sstream>
#include <fstream>

#include <iostream>
#include <cassert>

using namespace std;
using namespace llvm;

namespace cocl {
    // a Block has one or more links to child blocks
    // a Block can be linked to by one or more blocks
    // we probably need a root block, which holds the others
    static int nextId = 0;

    class Block {
    public:
        int id;
        Block() {
            this->id = nextId;
            nextId++;
        }
        virtual string blockType() const {
            return "Block";
        }
        virtual void dump(set<const Block *> &seen, string indent = "") const = 0;
        vector<Block *>incoming;
        virtual void replaceChild(Block *oldChild, Block *newChild) = 0;
    };
    class RootBlock : public Block {
    public:
        Block *first = 0;
        virtual string blockType() const {
            return "RootBlock";
        }
        virtual void dump(set<const Block *> &seen, string indent = "") const {
            seen.insert(this);
            cout << indent << "RootBlock " << this->id << endl;
            if(seen.find(first) == seen.end()) {
                first->dump(seen, indent + "  ");
            }
        }
        void replaceChild(Block *oldChild, Block *newChild) {
            assert(first == oldChild);
            first = newChild;
        }
    };
    class If : public Block {
    public:
        Value *condition = 0;
        Block *trueBlock = 0;
        Block *falseBlock = 0;
        virtual string blockType() const {
            return "If";
        }
        virtual void dump(set<const Block *> &seen, string indent) const {
            seen.insert(this);
            cout << indent << "If " << this->id << endl;
            cout << indent << "  True:" << endl;
            if(seen.find(trueBlock) == seen.end()) {
                trueBlock->dump(seen, indent + "    ");
            } else {
                cout << indent << "    (*" << trueBlock->id << endl;
            }
            if(falseBlock != 0) {
                cout << indent << "  False:" << endl;
                if(seen.find(falseBlock) == seen.end()) {
                    falseBlock->dump(seen, indent + "    ");
                } else {
                    cout << indent << "    (*" << falseBlock->id << endl;
                }
            }
        }
        void replaceChild(Block *oldChild, Block *newChild) {
            if(trueBlock == oldChild) {
                trueBlock = newChild;
                return;
            }
            if(falseBlock == oldChild) {
                falseBlock = newChild;
                return;
            }
            throw runtime_error("couldnt find old child");
        }
    };
    class ConditionalBranch : public Block {
    public:
        Value *condition = 0;
        Block *trueNext = 0;
        Block *falseNext = 0;
        virtual string blockType() const {
            return "ConditionalBranch";
        }
        virtual void dump(set<const Block *> &seen, string indent) const {
            seen.insert(this);
            cout << indent << "ConditionalBranch " << this->id << endl;
            cout << indent << "  True:" << endl;
            if(seen.find(trueNext) == seen.end()) {
                trueNext->dump(seen, indent + "    ");
            } else {
                cout << indent << "    (*" << trueNext->id << endl;
            }
            if(falseNext != 0) {
                cout << indent << "  False:" << endl;
                if(seen.find(falseNext) == seen.end()) {
                    falseNext->dump(seen, indent + "    ");
                } else {
                    cout << indent << "    (*" << falseNext->id << endl;
                }
            }
        }
        void replaceChild(Block *oldChild, Block *newChild) {
            if(trueNext == oldChild) {
                trueNext = newChild;
                return;
            }
            if(falseNext == oldChild) {
                falseNext = newChild;
                return;
            }
            throw runtime_error("couldnt find old child");
        }
    };
    class BasicBlockBlock : public Block {
    public:
        BasicBlock *basicBlock = 0;
        vector<Value *> instructions;
        Block *next; // initially will probalby point to a Branch block
        virtual string blockType() const {
            return "BasicBlockBlock";
        }
        virtual void dump(set<const Block *> &seen, string indent) const {
            seen.insert(this);
            cout << indent << "BasicBlockBlock " << this->id << endl;
            if(next == 0) {
                return;
            }
            if(seen.find(next) == seen.end()) {
                next->dump(seen, indent);
            } else {
                cout << indent << "  (*" << next->id << endl;
            }
        }
        void replaceChild(Block *oldChild, Block *newChild) {
            if(next == oldChild) {
                next = newChild;
                return;
            }
            throw runtime_error("couldnt find old child");
        }
    };
    class Sequence : public Block {
    public:
        vector<Block *> children;
        virtual string blockType() const {
            return "Sequence";
        }
        virtual void dump(set<const Block *> &seen, string indent) const {
            seen.insert(this);
            cout << indent << "Sequence " << this->id << endl;
            for(auto it = children.begin(); it != children.end(); it++) {
                Block *child = *it;
                if(seen.find(child) == seen.end()) {
                    child->dump(seen, indent + "  ");
                } else {
                    cout << indent << "  (*" << child->id << endl;
                }
            }
        }
        void replaceChild(Block *oldChild, Block *newChild) {
            int i = 0;
            bool foundChild = false;
            for(auto it = children.begin(); it != children.end(); it++) {
                Block *child = *it;
                if(child == oldChild) {
                    foundChild = true;
                    break;
                }
                i++;
            }
            if(foundChild) {
                children[i] = newChild;
                return;
            }
            throw runtime_error("couldnt find old child");
        }
    };
    class ReturnBlock : public Block {
    public:
        virtual string blockType() const {
            return "ReturnBlock";
        }
        virtual void dump(set<const Block *> &seen, string indent) const {
            cout << indent << "ReturnBlock " << this->id << endl;
        }
        void replaceChild(Block *oldChild, Block *newChild) {
            throw runtime_error("couldnt find old child");
        }
    };
    vector<unique_ptr<Block> > blocks; // doesnt include the root. I guess. ???
    map<BasicBlock *, Block *> blockByBasicBlock;

    // void dumpBlock(Block *block) {
    //     cout << "dumping block" << endl;
    //     block->dump();
    // }

    void mergeSequences(Block *root) {
        // basically we look for any block with one single incoming, and that incoming is a basicblockblock
        bool didAMerge = true;
        while(didAMerge) {
            didAMerge = false;
            for(auto it = blocks.begin(); it != blocks.end(); it++) {
                Block *block = it->get();
                if(block->incoming.size() == 1) {
                    // cout << "block " << block->id << " has only one incoming" << endl;
                    Block *parent = block->incoming[0];
                    if(BasicBlockBlock *parentBlockBlock = dynamic_cast<BasicBlockBlock*>(parent)) {
                        // cout << "its a blockblock" << endl;
                        if(BasicBlockBlock *thisBlockBlock = dynamic_cast<BasicBlockBlock*>(block)) {
                            // so merge...
                            cout << "merging ... " << block->id << ", " << parent->id << endl;
                            unique_ptr<Sequence> sequence(new Sequence());
                            sequence->children.push_back(parent);
                            sequence->children.push_back(block);
                            for(auto parentincit = parent->incoming.begin(); parentincit != parent->incoming.end(); parentincit++) {
                                Block *parentinc = *parentincit;
                                sequence->incoming.push_back(parentinc);
                                parentinc->replaceChild(parent, sequence.get());
                            }
                            parent->incoming.clear();
                            parent->incoming.push_back(sequence.get());
                            parentBlockBlock->next = 0;
                            block->incoming.clear();
                            block->incoming.push_back(sequence.get());
                            thisBlockBlock->next = 0;
                            blocks.push_back(std::move(sequence));
                            didAMerge = true;
                        }
                    } else {
                        // cout << "but not a basicblockblock" << endl;
                    }
                }
            }
        }
    }

    void handle_branching_simplify(Function *F) {
        cout << "simplify " << string(F->getName()) << endl;
        unique_ptr<RootBlock> root(new RootBlock());
        for(auto it=F->begin(); it != F->end(); it++) {
            cout << "block" << endl;
            BasicBlock *basicBlock = &*it;
            unique_ptr<BasicBlockBlock> block(new BasicBlockBlock());
            block->basicBlock = basicBlock;
            for(auto instit=basicBlock->begin(); instit != basicBlock->end(); instit++) {
                Instruction *inst = &*instit;
                // skip branches, phis and so on, which we'll handle later, somehow...
                if(isa<BranchInst>(inst)) {
                    continue;
                }
                if(isa<PHINode>(inst)) {
                    continue;
                }
                if(isa<ReturnInst>(inst)) {
                    continue;
                }
                block->instructions.push_back(inst);
            }
            blockByBasicBlock[basicBlock] = block.get();
            blocks.push_back(std::move(block));
        }

        root->first = blockByBasicBlock[&F->getEntryBlock()];
        root->first->incoming.push_back(root.get());
        // go through, and start linking stuff togehter, now that we have a map from basic block to block
        for(auto it=F->begin(); it != F->end(); it++) {
            BasicBlock *basicBlock = &*it;
            BasicBlockBlock *block = dynamic_cast<BasicBlockBlock *>(blockByBasicBlock[basicBlock]);
            // I think that each block has to end initially either with a branch or a return?
            Instruction *lastInst = basicBlock->getTerminator();
            cout << "lastinst:" << endl;
            lastInst->dump();
            cout << endl;
            if(isa<ReturnInst>(lastInst)) {
                cout << "finishes in ret" << endl;
                unique_ptr<ReturnBlock> retBlock(new ReturnBlock());
                block->next = retBlock.get();
                block->next->incoming.push_back(block);
                blocks.push_back(std::move(retBlock));
            } else if(BranchInst* branchInst = dyn_cast<BranchInst>(lastInst)) {
                cout << "its a branch" << endl;
                // if its unconditional, we just link directly to the next block
                // otherwise we link to a ConditionalBranch block
                if(branchInst->isUnconditional()) {
                    cout << "unconditonal branch" << endl;
                    BasicBlock *next = branchInst->getSuccessor(0);
                    Block *nextBlock = blockByBasicBlock[next];
                    block->next = nextBlock;
                    block->next->incoming.push_back(block);
                } else {
                    // conditional
                    // create a ConditionalBranch block
                    cout << "conditonal branch" << endl;
                    unique_ptr<ConditionalBranch> conditionalBranch(new ConditionalBranch());
                    BasicBlock *trueBasicBlock = branchInst->getSuccessor(0);
                    Block *trueBlock = blockByBasicBlock[trueBasicBlock];
                    conditionalBranch->trueNext = trueBlock;
                    conditionalBranch->trueNext->incoming.push_back(conditionalBranch.get());
                    conditionalBranch->falseNext = 0;
                    if(branchInst->getNumSuccessors() == 2) {
                        BasicBlock *falseBasicBlock = branchInst->getSuccessor(1);
                        Block *falseBlock = blockByBasicBlock[falseBasicBlock];
                        conditionalBranch->falseNext = falseBlock;
                        conditionalBranch->falseNext->incoming.push_back(conditionalBranch.get());
                    }
                    block->next = conditionalBranch.get();
                    block->next->incoming.push_back(block);
                    blocks.push_back(std::move(conditionalBranch));
                }
            } else {
                cout << "hmmm, how did we get here???" << endl;
                cout << "lastinst:" << endl;
                lastInst->dump();
                cout << endl;
                throw runtime_error("dont know how we got here...");
            }
        }

        set<const Block *>seen;
        root->dump(seen, "");

        mergeSequences(root.get());

        seen.clear();
        root->dump(seen, "");
    }
}
<|endoftext|>


<commit_before>#include "interface/uart.h"
#include "util/log.h"
#include <stddef.h>

const int openxc::interface::uart::MAX_MESSAGE_SIZE = 128;

void openxc::interface::uart::initializeCommon(UartDevice* device) {
    if(device != NULL) {
        debug("Initializing UART.....");
        QUEUE_INIT(uint8_t, &device->receiveQueue);
        QUEUE_INIT(uint8_t, &device->sendQueue);
    }
}
<commit_msg>Keep UART init logging on one line, as USB does.<commit_after>#include "interface/uart.h"
#include "util/log.h"
#include <stddef.h>

const int openxc::interface::uart::MAX_MESSAGE_SIZE = 128;

using openxc::util::log::debugNoNewline;

void openxc::interface::uart::initializeCommon(UartDevice* device) {
    if(device != NULL) {
        debugNoNewline("Initializing UART.....");
        QUEUE_INIT(uint8_t, &device->receiveQueue);
        QUEUE_INIT(uint8_t, &device->sendQueue);
    }
}
<|endoftext|>


<commit_before>/***************************************************************************
 *   Copyright (C) 2006, IBM                                               *
 *                                                                         *
 *   Maintained By:                                                        *
 *   Eric Munson and Brad Peters                                           *
 *   munsone@us.ibm.com, bpeters@us.ibm.com                                *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the Lesser GNU 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 program 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 Lesser GNU General Public      *
 *   License along with this program; if not, write to the                 *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include <libvpd-2/helper_functions.hpp>
#include <cstdio>
#include <fcntl.h>
#include <unistd.h>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <linux/limits.h>

#define BUF_SIZE PATH_MAX

using namespace std;
using namespace lsvpd;

	/**
	 * findAIXFSEntry
	 * @brief Finds AIX name which exists as a file or link in the dir
	 * 	'rootPath'
	 */
	string HelperFunctions::findAIXFSEntry(vector <DataItem*> aixNames,
											const string& rootPath)
	{
		string fin;
		int fd;
		vector<DataItem*>::const_iterator i, end;
		i = aixNames.begin();
		end = aixNames.end();

		while (i != end) {
			fin = rootPath + (*i)->getValue();
			fd = open( fin.c_str( ), O_RDONLY | O_NONBLOCK );
			if( fd < 0 )
				i++;
			else {
				close(fd);
				return fin;
			}
		}
		return string("");
	}

/**
 * parseString
 * @brief Parses out strings based on a count of position [0...x],
 *  with beginning and end of each string given by a '"'.
 * Ex: '"string 0" ... "string 1" ... "string 2" ...
 */
string HelperFunctions::parseString(const string& line, int str_pos, string& out)
{
	unsigned int pos = 0;
	int beg, len, count = 0;

	do {
		beg = line.find('"', pos) + 1;
		pos = line.find('"', beg) + 1;
		len = pos - beg;
		count++;
		} while  ((pos != string::npos) && (count < str_pos));

	out = line.substr(beg, len - 1);
	return out;
}

	/**
	 * parsePathr
	 * @brief Reverse parse of a path, returning the node specified by 'count'
	 * @param count 0 is the tail node, 1 is 1 in, etc.
	 * @example path = /sys/devices/x/y/z,
	 * @ex count = 0, returns z
	 *  count = 1, returns y
	 *  count = 2, returns x
	 */
	string HelperFunctions::parsePathr(const string& path, int count)
	{
		int beg, end;
		int i = count;

		if( path == "" )
			return path;

		beg = end = path.length();

		if (path[end] == '/')
			beg--;

		cout << "String: " << path << endl;

		while (i >= 0) {
			end = beg - 1;
			cout << "RFind Bef: beg: " << beg << ", end: " << end << ", i: " << i << endl;
			beg = path.rfind("/", end - 1) + 1;
			cout << "RFind : beg: " << beg << ", end: " << end << ", i: " << i << endl;
			i--;
		}

		return path.substr(beg, end - beg);
	}

	/**
	 * parsePath
	 * @brief Parse of a path, returning the node specified by 'count'
	 * @param count 0 is the first node, 1 is 1 in, etc.
	 * @example path = /sys/devices/x/y/z,
	 * @ex count = 0, returns sys
	 *  count = 1, returns devices
	 *  count = 2, returns x
	 */
	string HelperFunctions::parsePath(const string& path, int count)
	{
		int beg = 0, end, i = count;

		if( path == "" )
			return path;

		if (path[end] == '/')
			end--;

		while (i >= 0) {
			beg = path.find("/", beg) + 1;
			i--;
		}

		end = path.find("/", beg);

		return path.substr(beg, end - beg);
	}

	/**
	 * getSymLinkTarget
	 * @brief Returns the absolute path pointed at by a sym link
	 * @param full path of sym link
	 * @return String abs target
	 */
	string HelperFunctions::getSymLinkTarget(const string& symLinkPath)
	{
		char linkTarget[BUF_SIZE], *buf = NULL;
		memset (linkTarget, 0, BUF_SIZE);

		buf = strdup(symLinkPath.c_str());
		if (buf !=  NULL)
			readlink(buf, linkTarget, BUF_SIZE - 1);

		return string(getAbsolutePath(linkTarget, buf));
	}

/* Drops one dir entry on the end of a path
	 * @return Returns number of dirs successfully dropped*/
	int HelperFunctions::dropDir(char * filePath)
	{
		int len = strlen(filePath);
		int i, ret = 0;

		if (len <= 0)
			return 0;

		/* erase filenames */
		i = len;
		while (i > 0 && filePath[i] != '/')
			filePath[i--] = '\0';

		filePath[len-1] = '\0'; //erase trailing '/'

		i = len;
		while (i > 0 && filePath[i] != '/') {
			filePath[i--] = '\0';
			ret = 1;
		}

		return ret;
	}

	/* Drops one dir entry on the end of a path
	 * @return Returns number of dirs successfully dropped*/
	int HelperFunctions::dropDir(string& filePath_t)
	{
		int len = filePath_t.length();
		int i, ret = 0;
		char *filePath;

		filePath = strdup(filePath_t.c_str());

		if (len <= 0) {
			free(filePath);
			return 0;
		}

		/* erase filenames */
		i = len;
		while (i > 0 && filePath[i] != '/')
			filePath[i--] = '\0';

		filePath[len-1] = '\0'; //erase trailing '/'

		i = len;
		while (i > 0 && filePath[i] != '/') {
			filePath[i--] = '\0';
			ret = 1;
		}
		filePath[i--] = '\0';

		filePath_t = string(filePath);
		free(filePath);
		return ret;
	}

	/* @brief Drops dirs from curDir, 1 for each '../', then add remainder of filePath
	 * to curDir */
	string HelperFunctions::getAbsolutePath(char * relPath, char * curDir)
	{
		int len = strlen(relPath);
		int i = strlen(curDir);
		string tmp;

        if (len <= 0 || i <= 0)
        	return string();

		while (i > 0 && curDir[i] != '/')
			curDir[i--] = '\0';

		i = 0;
		while (strncmp(&relPath[i * 3], "../", 3) == 0) {
        	dropDir(curDir);
        	i++;
        }

        tmp = string(curDir) + string(&relPath[i * 3]);

        return tmp;
	}

	/**
	 * Takes two strings and finds if the two are equivalent.
	 * s1 can contain '*', meaning zero or more of anything can be
	 * counted as a match
	 */
	bool HelperFunctions::matches(const string& s1, const string& s2)
	{
		unsigned int beg = 0, end = s1.length();
		unsigned int z;
//		coutd << " s1 = " << s1 << ", s2 = " << s2 << endl;

		//strings have matched to end - base case
		if ((s1 == s2) || (s1.length() == 0) || (s2.length() == 0)) {
			return (s1 == s2);
		}

		//s1 has matched all the way up to a * - base case
		if (s1 == "*") {
			return true;
		}

		if (s1[0] == '*') {
			/*
			 * Need to grab a substring of s2, up to size of s1 from
			 * star to any other star
			 */
			beg = 1;
			end = s1.length();

			if ( string::npos == (end = s1.find("*", beg))) {
				//No more stars - base case
				if (string::npos != (z = s2.find(s1.substr(beg, end), 0))) {
					return true;
				}
			}
			else {
				if (string::npos != s2.find(s1.substr(beg, end), 0))
					matches(s1.substr(end, s1.length() - end),
							s2.substr(end, s2.length() - end));
			}
		}
		else
			end = s1.find("*", 0);

		if (s1.substr(beg, end) == s2.substr(beg, end)) {
			return matches(s1.substr(end, s1.length() - end),
						s2.substr(end, s2.length() - end));
		}
		else {
			return false;
		}
	}

	/* Caller responsible for deleting new'd memory */
	void HelperFunctions::str2chr(char **str1, const string& str2)
		{
			unsigned int i;
			*str1 = new char[ str2.length( ) * sizeof( char ) ];

			i=0;
			while (i < str2.length())
			{
				(*str1)[i] = str2[i];
				i++;
			}

			(*str1)[i] = '\0';
		}

	/* @brief Ensure a passed in fs path arg is in reasonable format */
	void HelperFunctions::fs_fixPath(string& str)
	{
		int i = str.length();

		while (str[i] == '\0')
			i--;
		if (str[i] == '/')
			str[i] = '\0';
	}

	/* @brief Ensure a passed in fs path arg is in reasonable format */
	char *HelperFunctions::fs_fixPath(char *path_t)
	{
		char *path;
		char *chr;

		path = strdup(path_t);
		/* Basic wierdness checking*/
			chr = &path[strlen(path)];
			while (chr != '\0')
				chr--;
			if (*chr == '/')
				*chr = '\0';

		return path;
	}

	bool HelperFunctions::file_exists(const string& file)
	{
		FILE *f = fopen(file.c_str(), "r");
		if (!f) return false;
		fclose(f);
		return true;
	}

/** readMatchFromFile
 *  @brief Returns first matching line from specified file,
 *    in which was found a match to the specified string
*/
string HelperFunctions::readMatchFromFile(const string& file,
											const string& str)
{
	char buf[BUF_SIZE];
	string line;

	if (file_exists(file)) {
		ifstream fin(file.c_str());

		while(!fin.eof()) {
			fin.getline(buf,BUF_SIZE - 1);
			line = string(buf);
			int loc = line.find(str);
			if (loc == 0) {
				return line;
			}
		}
		return string("");
	}
	return string("");
}

	int HelperFunctions::countChar( const string& str, char c )
	{
		string::const_iterator i, end;
		int ret = 0;
		for( i = str.begin( ), end = str.end( ); i != end; ++i )
		{
			if( (*i) == c )
			{
				ret++;
			}
		}
		return ret;
	}

	bool HelperFunctions::contains( const vector<DataItem*>& vec,
		const string& val )
	{
		vector<DataItem*>::const_iterator i, end;
		for( i = vec.begin( ), end = vec.end( ); i != end; ++i )
		{
			if( (*i)->getValue( ) == val )
				return true;
		}

		return false;
	}

	int HelperFunctions::execCmd( const char *cmd, string& output )
	{
		char buf[BUF_SIZE];
		FILE *fp = popen(cmd, "r");

		if (fp == NULL)
			return 1;

		while ( !feof(fp) )
			if (fgets(buf, BUF_SIZE - 1, fp) != NULL)
				output += buf;
		pclose(fp);
		return 0;
	}
<commit_msg>libvpd: Close file descriptors.<commit_after>/***************************************************************************
 *   Copyright (C) 2006, IBM                                               *
 *                                                                         *
 *   Maintained By:                                                        *
 *   Eric Munson and Brad Peters                                           *
 *   munsone@us.ibm.com, bpeters@us.ibm.com                                *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the Lesser GNU 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 program 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 Lesser GNU General Public      *
 *   License along with this program; if not, write to the                 *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include <libvpd-2/helper_functions.hpp>
#include <cstdio>
#include <fcntl.h>
#include <unistd.h>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <linux/limits.h>

#define BUF_SIZE PATH_MAX

using namespace std;
using namespace lsvpd;

	/**
	 * findAIXFSEntry
	 * @brief Finds AIX name which exists as a file or link in the dir
	 * 	'rootPath'
	 */
	string HelperFunctions::findAIXFSEntry(vector <DataItem*> aixNames,
											const string& rootPath)
	{
		string fin;
		int fd;
		vector<DataItem*>::const_iterator i, end;
		i = aixNames.begin();
		end = aixNames.end();

		while (i != end) {
			fin = rootPath + (*i)->getValue();
			fd = open( fin.c_str( ), O_RDONLY | O_NONBLOCK );
			if( fd < 0 )
				i++;
			else {
				close(fd);
				return fin;
			}
		}
		return string("");
	}

/**
 * parseString
 * @brief Parses out strings based on a count of position [0...x],
 *  with beginning and end of each string given by a '"'.
 * Ex: '"string 0" ... "string 1" ... "string 2" ...
 */
string HelperFunctions::parseString(const string& line, int str_pos, string& out)
{
	unsigned int pos = 0;
	int beg, len, count = 0;

	do {
		beg = line.find('"', pos) + 1;
		pos = line.find('"', beg) + 1;
		len = pos - beg;
		count++;
		} while  ((pos != string::npos) && (count < str_pos));

	out = line.substr(beg, len - 1);
	return out;
}

	/**
	 * parsePathr
	 * @brief Reverse parse of a path, returning the node specified by 'count'
	 * @param count 0 is the tail node, 1 is 1 in, etc.
	 * @example path = /sys/devices/x/y/z,
	 * @ex count = 0, returns z
	 *  count = 1, returns y
	 *  count = 2, returns x
	 */
	string HelperFunctions::parsePathr(const string& path, int count)
	{
		int beg, end;
		int i = count;

		if( path == "" )
			return path;

		beg = end = path.length();

		if (path[end] == '/')
			beg--;

		cout << "String: " << path << endl;

		while (i >= 0) {
			end = beg - 1;
			cout << "RFind Bef: beg: " << beg << ", end: " << end << ", i: " << i << endl;
			beg = path.rfind("/", end - 1) + 1;
			cout << "RFind : beg: " << beg << ", end: " << end << ", i: " << i << endl;
			i--;
		}

		return path.substr(beg, end - beg);
	}

	/**
	 * parsePath
	 * @brief Parse of a path, returning the node specified by 'count'
	 * @param count 0 is the first node, 1 is 1 in, etc.
	 * @example path = /sys/devices/x/y/z,
	 * @ex count = 0, returns sys
	 *  count = 1, returns devices
	 *  count = 2, returns x
	 */
	string HelperFunctions::parsePath(const string& path, int count)
	{
		int beg = 0, end, i = count;

		if( path == "" )
			return path;

		if (path[end] == '/')
			end--;

		while (i >= 0) {
			beg = path.find("/", beg) + 1;
			i--;
		}

		end = path.find("/", beg);

		return path.substr(beg, end - beg);
	}

	/**
	 * getSymLinkTarget
	 * @brief Returns the absolute path pointed at by a sym link
	 * @param full path of sym link
	 * @return String abs target
	 */
	string HelperFunctions::getSymLinkTarget(const string& symLinkPath)
	{
		char linkTarget[BUF_SIZE], *buf = NULL;
		memset (linkTarget, 0, BUF_SIZE);

		buf = strdup(symLinkPath.c_str());
		if (buf !=  NULL)
			readlink(buf, linkTarget, BUF_SIZE - 1);

		return string(getAbsolutePath(linkTarget, buf));
	}

/* Drops one dir entry on the end of a path
	 * @return Returns number of dirs successfully dropped*/
	int HelperFunctions::dropDir(char * filePath)
	{
		int len = strlen(filePath);
		int i, ret = 0;

		if (len <= 0)
			return 0;

		/* erase filenames */
		i = len;
		while (i > 0 && filePath[i] != '/')
			filePath[i--] = '\0';

		filePath[len-1] = '\0'; //erase trailing '/'

		i = len;
		while (i > 0 && filePath[i] != '/') {
			filePath[i--] = '\0';
			ret = 1;
		}

		return ret;
	}

	/* Drops one dir entry on the end of a path
	 * @return Returns number of dirs successfully dropped*/
	int HelperFunctions::dropDir(string& filePath_t)
	{
		int len = filePath_t.length();
		int i, ret = 0;
		char *filePath;

		filePath = strdup(filePath_t.c_str());

		if (len <= 0) {
			free(filePath);
			return 0;
		}

		/* erase filenames */
		i = len;
		while (i > 0 && filePath[i] != '/')
			filePath[i--] = '\0';

		filePath[len-1] = '\0'; //erase trailing '/'

		i = len;
		while (i > 0 && filePath[i] != '/') {
			filePath[i--] = '\0';
			ret = 1;
		}
		filePath[i--] = '\0';

		filePath_t = string(filePath);
		free(filePath);
		return ret;
	}

	/* @brief Drops dirs from curDir, 1 for each '../', then add remainder of filePath
	 * to curDir */
	string HelperFunctions::getAbsolutePath(char * relPath, char * curDir)
	{
		int len = strlen(relPath);
		int i = strlen(curDir);
		string tmp;

        if (len <= 0 || i <= 0)
        	return string();

		while (i > 0 && curDir[i] != '/')
			curDir[i--] = '\0';

		i = 0;
		while (strncmp(&relPath[i * 3], "../", 3) == 0) {
        	dropDir(curDir);
        	i++;
        }

        tmp = string(curDir) + string(&relPath[i * 3]);

        return tmp;
	}

	/**
	 * Takes two strings and finds if the two are equivalent.
	 * s1 can contain '*', meaning zero or more of anything can be
	 * counted as a match
	 */
	bool HelperFunctions::matches(const string& s1, const string& s2)
	{
		unsigned int beg = 0, end = s1.length();
		unsigned int z;
//		coutd << " s1 = " << s1 << ", s2 = " << s2 << endl;

		//strings have matched to end - base case
		if ((s1 == s2) || (s1.length() == 0) || (s2.length() == 0)) {
			return (s1 == s2);
		}

		//s1 has matched all the way up to a * - base case
		if (s1 == "*") {
			return true;
		}

		if (s1[0] == '*') {
			/*
			 * Need to grab a substring of s2, up to size of s1 from
			 * star to any other star
			 */
			beg = 1;
			end = s1.length();

			if ( string::npos == (end = s1.find("*", beg))) {
				//No more stars - base case
				if (string::npos != (z = s2.find(s1.substr(beg, end), 0))) {
					return true;
				}
			}
			else {
				if (string::npos != s2.find(s1.substr(beg, end), 0))
					matches(s1.substr(end, s1.length() - end),
							s2.substr(end, s2.length() - end));
			}
		}
		else
			end = s1.find("*", 0);

		if (s1.substr(beg, end) == s2.substr(beg, end)) {
			return matches(s1.substr(end, s1.length() - end),
						s2.substr(end, s2.length() - end));
		}
		else {
			return false;
		}
	}

	/* Caller responsible for deleting new'd memory */
	void HelperFunctions::str2chr(char **str1, const string& str2)
		{
			unsigned int i;
			*str1 = new char[ str2.length( ) * sizeof( char ) ];

			i=0;
			while (i < str2.length())
			{
				(*str1)[i] = str2[i];
				i++;
			}

			(*str1)[i] = '\0';
		}

	/* @brief Ensure a passed in fs path arg is in reasonable format */
	void HelperFunctions::fs_fixPath(string& str)
	{
		int i = str.length();

		while (str[i] == '\0')
			i--;
		if (str[i] == '/')
			str[i] = '\0';
	}

	/* @brief Ensure a passed in fs path arg is in reasonable format */
	char *HelperFunctions::fs_fixPath(char *path_t)
	{
		char *path;
		char *chr;

		path = strdup(path_t);
		/* Basic wierdness checking*/
			chr = &path[strlen(path)];
			while (chr != '\0')
				chr--;
			if (*chr == '/')
				*chr = '\0';

		return path;
	}

	bool HelperFunctions::file_exists(const string& file)
	{
		FILE *f = fopen(file.c_str(), "r");
		if (!f) return false;
		fclose(f);
		return true;
	}

/** readMatchFromFile
 *  @brief Returns first matching line from specified file,
 *    in which was found a match to the specified string
*/
string HelperFunctions::readMatchFromFile(const string& file,
											const string& str)
{
	char buf[BUF_SIZE];
	string line;

	if (file_exists(file)) {
		ifstream fin(file.c_str());

		while(!fin.eof()) {
			fin.getline(buf,BUF_SIZE - 1);
			line = string(buf);
			int loc = line.find(str);
			if (loc == 0) {
				fin.close();
				return line;
			}
		}
		fin.close();
		return string("");
	}
	return string("");
}

	int HelperFunctions::countChar( const string& str, char c )
	{
		string::const_iterator i, end;
		int ret = 0;
		for( i = str.begin( ), end = str.end( ); i != end; ++i )
		{
			if( (*i) == c )
			{
				ret++;
			}
		}
		return ret;
	}

	bool HelperFunctions::contains( const vector<DataItem*>& vec,
		const string& val )
	{
		vector<DataItem*>::const_iterator i, end;
		for( i = vec.begin( ), end = vec.end( ); i != end; ++i )
		{
			if( (*i)->getValue( ) == val )
				return true;
		}

		return false;
	}

	int HelperFunctions::execCmd( const char *cmd, string& output )
	{
		char buf[BUF_SIZE];
		FILE *fp = popen(cmd, "r");

		if (fp == NULL)
			return 1;

		while ( !feof(fp) )
			if (fgets(buf, BUF_SIZE - 1, fp) != NULL)
				output += buf;
		pclose(fp);
		return 0;
	}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <memory>

#include "gsl/gsl_poly.h"

#include "ConfigFile.h"
#include "Run.h"
#include "Particle.h"
#include "TTree.h"
#include "TFile.h"
#include "TH1F.h"
#include "TGraphErrors.h"
#include "TF1.h"
#include "TCanvas.h"
#include "TMath.h"
#include "TRint.h"
#include "TVector3.h"
#include "TGeoMatrix.h"
#include "UniformMagField.h"
#include "MagFieldArray.h"
#include "Data.h"
#include "FieldMap.h"
#include "FileParser.h"
#include "Tube.h"
#include "Polynomial.h"

#include "Constants.h"
#include "Units.h"
#include "GeomParameters.h"
#include "DataAnalysis.h"

using namespace std;

Int_t calculate_T2(string configFileName, vector<string> stateNames);

//__________________________________________________________________________
Int_t main(Int_t argc,Char_t ** argv)
{
   if (argc < 3) {
      cerr << "Usage:" << endl;
      cerr << "sandbox <data.root> <statename>" << endl;
      return EXIT_FAILURE;
   }
   // Read in Filename and check that it is a .root file
   string configFileName = argv[1];
   // Read in list of states to be included in histogram and check that they are valid state names
   vector<string> stateNames;
   for (int i = 2; i < argc; i++) {stateNames.push_back(argv[i]);}
   if (Analysis::DataFile::IsValidStateName(stateNames) == false) {
      cerr << "Error: statenames supplied are not valid" << endl;
      return EXIT_FAILURE;
   }
   TRint *theApp = new TRint("FittingApp", NULL, NULL);
   calculate_T2(configFileName, stateNames);
   theApp->Run();
   return EXIT_SUCCESS;
}

//_____________________________________________________________________________
Int_t calculate_T2(string configFileName, vector<string> stateNames) {

   ///////////////////////////////////////////////////////////////////////////////////////
   // Build the ConfigFile
   ConfigFile configFile(configFileName);
   ///////////////////////////////////////////////////////////////////////////////////////
   // Fetch the Number of Runs
   const int numberOfRuns = configFile.GetInt("NumberOfRuns","Runs");
   if (numberOfRuns < 1) {
      cerr << "Cannot read valid number of runs from ConfigFile: " << numberOfRuns << endl;
      return -1;
   }
   ///////////////////////////////////////////////////////////////////////////////////////
   // Loop over runs specified in ConfigFile
   for (int runNum = 1; runNum <= numberOfRuns; runNum++) {
      // Load Run Config for this run
      RunConfig runConfig(configFile, runNum);
      // Fetch this run's Data file
      const string dataFileName = runConfig.OutputFileName();
      TFile* dataFile = Analysis::DataFile::OpenRootFile(dataFileName, "UPDATE");
      // Calculate T2 for this run
      double t2 = 0., t2error = 0.;
      if (Analysis::Spins::CalculateT2(*dataFile, stateNames, t2, t2error) == false) {
         cerr << "Failed to calculate T2 for datafile: " << dataFileName << endl;
         return -1;
      }
      // Add T2 to graph
      cout << "T2: " << t2 << "\t" << "Error: " << t2error << endl;
   }
   ///////////////////////////////////////////////////////////////////////////////////////
   // Draw Graph

   return 0;
}
<commit_msg>Add plotting T2 vs run number in sandbox<commit_after>#include <iostream>
#include <string>
#include <memory>

#include "gsl/gsl_poly.h"

#include "ConfigFile.h"
#include "Run.h"
#include "Particle.h"
#include "TTree.h"
#include "TFile.h"
#include "TH1F.h"
#include "TGraphErrors.h"
#include "TF1.h"
#include "TCanvas.h"
#include "TMath.h"
#include "TRint.h"
#include "TVector3.h"
#include "TGeoMatrix.h"
#include "UniformMagField.h"
#include "MagFieldArray.h"
#include "Data.h"
#include "FieldMap.h"
#include "FileParser.h"
#include "Tube.h"
#include "Polynomial.h"

#include "Constants.h"
#include "Units.h"
#include "GeomParameters.h"
#include "DataAnalysis.h"

using namespace std;

Int_t calculate_T2(string configFileName, vector<string> stateNames);

//__________________________________________________________________________
Int_t main(Int_t argc,Char_t ** argv)
{
   if (argc < 3) {
      cerr << "Usage:" << endl;
      cerr << "sandbox <data.root> <statename>" << endl;
      return EXIT_FAILURE;
   }
   // Read in Filename and check that it is a .root file
   string configFileName = argv[1];
   // Read in list of states to be included in histogram and check that they are valid state names
   vector<string> stateNames;
   for (int i = 2; i < argc; i++) {stateNames.push_back(argv[i]);}
   if (Analysis::DataFile::IsValidStateName(stateNames) == false) {
      cerr << "Error: statenames supplied are not valid" << endl;
      return EXIT_FAILURE;
   }
//   TRint *theApp = new TRint("FittingApp", NULL, NULL);
   calculate_T2(configFileName, stateNames);
//   theApp->Run();
   return EXIT_SUCCESS;
}

//_____________________________________________________________________________
Int_t calculate_T2(string configFileName, vector<string> stateNames) {

   ///////////////////////////////////////////////////////////////////////////////////////
   // Build the ConfigFile
   ConfigFile configFile(configFileName);
   ///////////////////////////////////////////////////////////////////////////////////////
   // Fetch the Number of Runs
   const int numberOfRuns = configFile.GetInt("NumberOfRuns","Runs");
   if (numberOfRuns < 1) {
      cerr << "Cannot read valid number of runs from ConfigFile: " << numberOfRuns << endl;
      return -1;
   }
   // Make T2 graph
   TGraphErrors* graph = new TGraphErrors(numberOfRuns);
   ///////////////////////////////////////////////////////////////////////////////////////
   // Loop over runs specified in ConfigFile
   for (int runNum = 1; runNum <= numberOfRuns; runNum++) {
      // Load Run Config for this run
      RunConfig runConfig(configFile, runNum);
      // Fetch this run's Data file
      const string dataFileName = runConfig.OutputFileName();
      TFile* dataFile = Analysis::DataFile::OpenRootFile(dataFileName, "UPDATE");
      // Calculate T2 for this run
      double t2 = 0., t2error = 0.;
      if (Analysis::Spins::CalculateT2(*dataFile, stateNames, t2, t2error) == false) {
         cerr << "Failed to calculate T2 for datafile: " << dataFileName << endl;
         return -1;
      }
      // Add T2 to graph
      cout << "T2: " << t2 << "\t" << "Error: " << t2error << endl;
      graph->SetPoint(runNum-1, runNum, t2);
      graph->SetPointError(runNum-1, 0, t2error);
      // Close File
      dataFile->Close();
      delete dataFile;
   }
   ///////////////////////////////////////////////////////////////////////////////////////
   // Draw Graph
   TCanvas* canvas = new TCanvas("Phase","Phase",60,0,1200,800);
   canvas->cd();
   graph->SetMarkerStyle(8);
   graph->Draw("AP");
   graph->GetXaxis()->SetTitle("Config Num");
   graph->GetYaxis()->SetTitle("T2 (s)");
   graph->GetYaxis()->SetRangeUser(0.0, 20.0);
   graph->SetTitle("T2");
   // Write canvas to file
   canvas->SaveAs("t2.png");
   // Clean up graph
   delete graph;
   delete canvas;
   return 0;
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2008 University of North Carolina at Chapel Hill

This file is part of SSBA (Simple Sparse Bundle Adjustment).

SSBA 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 3 of the License, or (at your option) any
later version.

SSBA 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 SSBA. If not, see <http://www.gnu.org/licenses/>.
*/

// Bundle adjustment application for datasets captured with different cameras (varying intrinsics).

#include "Math/v3d_linear.h"
#include "Math/v3d_linear_utils.h"
#include "Geometry/v3d_metricbundle.h"

#include <cstring>

#include <iostream>
#include <fstream>
#include <map>

using namespace V3D;
using namespace std;

namespace
{

   inline void
   showErrorStatistics(vector<double> const& origFocalLengths,
                       vector<StdDistortionFunction> const& distortions,
                       vector<CameraMatrix> const& cams,
                       vector<Vector3d> const& Xs,
                       vector<Vector2d> const& measurements,
                       vector<int> const& correspondingView,
                       vector<int> const& correspondingPoint)
   {
      int const K = measurements.size();

      double meanReprojectionError = 0.0;
      for (int k = 0; k < K; ++k)
      {
         int const i = correspondingView[k];
         int const j = correspondingPoint[k];
         Vector2d p = cams[i].projectPoint(distortions[i], Xs[j]);

         double const f0 = origFocalLengths[i];
         double reprojectionError = norm_L2(f0 * (p - measurements[k]));
         meanReprojectionError += reprojectionError;
      }
      cout << "mean reprojection error (in pixels): " << meanReprojectionError/K << endl;
   }

} // end namespace <>

int
main(int argc, char * argv[])
{
   if (argc != 3)
   {
      cerr << "Usage: " << argv[0] << " <sparse reconstruction file> <mode>" << endl;
      cout << "<mode> is one of metric, focal, prinipal, radial, tangental." << endl;
      return -1;
   }

   ifstream is(argv[1]);
   if (!is)
   {
      cerr << "Cannot open " << argv[1] << endl;
      return -2;
   }

   int mode = 0;
   if (strcmp(argv[2], "metric") == 0)
      mode = FULL_BUNDLE_METRIC;
   else if (strcmp(argv[2], "focal") == 0)
      mode = FULL_BUNDLE_FOCAL_LENGTH;
   else if (strcmp(argv[2], "principal") == 0)
      mode = FULL_BUNDLE_FOCAL_LENGTH_PP;
   else if (strcmp(argv[2], "radial") == 0)
      mode = FULL_BUNDLE_RADIAL;
   else if (strcmp(argv[2], "tangential") == 0)
      mode = FULL_BUNDLE_RADIAL_TANGENTIAL;
   else
   {
      cerr << "Unknown bundle mode: " << argv[2] << endl;
      return -2;
   }

   int N, M, K;
   is >> M >> N >> K;
   cout << "N (cams) = " << N << " M (points) = " << M << " K (measurements) = " << K << endl;

   vector<StdDistortionFunction> distortions(N);
   vector<double> origFocalLengths(N);
   vector<CameraMatrix> cams(N);

   double avgFocalLength = 0.0;

   for (int i = 0; i < N; ++i)
   {
      Matrix3x3d KMat;
      makeIdentityMatrix(KMat);
      is >> KMat[0][0] >> KMat[0][1] >> KMat[0][2] >> KMat[1][1] >> KMat[1][2]
         >> distortions[i].k1 >> distortions[i].k2 >> distortions[i].p1 >> distortions[i].p2;

      double const f0 = KMat[0][0];
      Matrix3x3d Knorm = KMat;
      // Normalize the intrinsic to have unit focal length.
      scaleMatrixIP(1.0/f0, Knorm);
      Knorm[2][2] = 1.0;

      origFocalLengths[i] = f0;
      cams[i].setIntrinsic(Knorm);
      avgFocalLength += f0;
   } // end for (i)

   avgFocalLength /= N;
   cout << "mean focal length = " << avgFocalLength << endl;

   vector<int> pointIdFwdMap(M);
   map<int, int> pointIdBwdMap;

   vector<Vector3d > Xs(M);
   for (int j = 0; j < M; ++j)
   {
      int pointId;
      is >> pointId >> Xs[j][0] >> Xs[j][1] >> Xs[j][2];
      pointIdFwdMap[j] = pointId;
      pointIdBwdMap.insert(make_pair(pointId, j));
   }
   cout << "Read the 3D points." << endl;

   vector<int> camIdFwdMap(N);
   map<int, int> camIdBwdMap;

   for (int i = 0; i < N; ++i)
   {
      int camId;
      Matrix3x3d R;
      Vector3d T;

      is >> camId;
      is >> R[0][0] >> R[0][1] >> R[0][2] >> T[0];
      is >> R[1][0] >> R[1][1] >> R[1][2] >> T[1];
      is >> R[2][0] >> R[2][1] >> R[2][2] >> T[2];

      camIdFwdMap[i] = camId;
      camIdBwdMap.insert(make_pair(camId, i));

#if 1
      cams[i].setRotation(R);
      cams[i].setTranslation(T);
#else
      cams[i].setRotation(transposedMatrix(R));
      cams[i].setTranslation(transposedMatrix(R) * (-1.0 * T));
#endif
   }
   cout << "Read the cameras." << endl;

   vector<Vector2d > measurements;
   vector<int> correspondingView;
   vector<int> correspondingPoint;

   measurements.reserve(K);
   correspondingView.reserve(K);
   correspondingPoint.reserve(K);

   for (int k = 0; k < K; ++k)
   {
      int view, point;
      Vector3d p, np;

      is >> view >> point;
      is >> p[0] >> p[1] >> p[2];

      if (camIdBwdMap.find(view) != camIdBwdMap.end() &&
          pointIdBwdMap.find(point) != pointIdBwdMap.end())
      {
         int const i = (*camIdBwdMap.find(view)).second;
         double const f0 = origFocalLengths[i];
         // Normalize the measurements to match the unit focal length.
         scaleVectorIP(1.0/f0, p);
         measurements.push_back(makeVector2(p[0], p[1]));
         correspondingView.push_back(camIdBwdMap[view]);
         correspondingPoint.push_back(pointIdBwdMap[point]);
      }
   } // end for (k)

   K = measurements.size();

   cout << "Read " << K << " valid 2D measurements." << endl;

   showErrorStatistics(origFocalLengths, distortions, cams, Xs,
                       measurements, correspondingView, correspondingPoint);

   V3D::optimizerVerbosenessLevel = 1;
   double const inlierThreshold = 2.0 / avgFocalLength;

   Matrix3x3d K0 = cams[0].getIntrinsic();
   cout << "K0 = "; displayMatrix(K0);

   VaryingInternalsMetricBundleOptimizer opt(mode, inlierThreshold, distortions, cams, Xs,
                                             measurements, correspondingView, correspondingPoint);
   opt.maxIterations = 50;
   opt.minimize();
   cout << "optimizer status = " << opt.status << endl;

   showErrorStatistics(origFocalLengths, distortions, cams, Xs,
                       measurements, correspondingView, correspondingPoint);

   ofstream os("refined.txt");

   os << M << " " << N << " " << K << endl;

   for (int i = 0; i < N; ++i)
   {
      Matrix3x3d Knew = cams[i].getIntrinsic();
      scaleMatrixIP(origFocalLengths[i], Knew);
      Knew[2][2] = 1.0;
      os << Knew[0][0] << " " << Knew[0][1] << " " << Knew[0][2] << " " << Knew[1][1] << " " << Knew[1][2] << " "
         << distortions[i].k1 << " " << distortions[i].k2 << " "
         << distortions[i].p1 << " " << distortions[i].p2 << " " << endl;
   }

   for (int j = 0; j < M; ++j)
   {
      os << pointIdFwdMap[j] << " " << Xs[j][0] << " " << Xs[j][1] << " " << Xs[j][2] << endl;
   }

   for (int i = 0; i < N; ++i)
   {
      os << camIdFwdMap[i] << " ";
      Matrix3x4d const RT = cams[i].getOrientation();
      os << RT[0][0] << " " << RT[0][1] << " " << RT[0][2] << " " << RT[0][3] << " ";
      os << RT[1][0] << " " << RT[1][1] << " " << RT[1][2] << " " << RT[1][3] << " ";
      os << RT[2][0] << " " << RT[2][1] << " " << RT[2][2] << " " << RT[2][3] << endl;
   }

   return 0;
}
<commit_msg>Changes based on comments.<commit_after>/*
Copyright (c) 2008 University of North Carolina at Chapel Hill

This file is part of SSBA (Simple Sparse Bundle Adjustment).

SSBA 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 3 of the License, or (at your option) any
later version.

SSBA 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 SSBA. If not, see <http://www.gnu.org/licenses/>.
*/

// Bundle adjustment application for datasets captured with different cameras (varying intrinsics).

#include "Math/v3d_linear.h"
#include "Math/v3d_linear_utils.h"
#include "Geometry/v3d_metricbundle.h"

#include <cstring>
#include <iostream>
#include <fstream>
#include <map>

using namespace V3D;
using namespace std;

namespace
{

   inline void
   showErrorStatistics(vector<double> const& origFocalLengths,
                       vector<StdDistortionFunction> const& distortions,
                       vector<CameraMatrix> const& cams,
                       vector<Vector3d> const& Xs,
                       vector<Vector2d> const& measurements,
                       vector<int> const& correspondingView,
                       vector<int> const& correspondingPoint)
   {
      int const K = measurements.size();

      double meanReprojectionError = 0.0;
      for (int k = 0; k < K; ++k)
      {
         int const i = correspondingView[k];
         int const j = correspondingPoint[k];
         Vector2d p = cams[i].projectPoint(distortions[i], Xs[j]);

         double const f0 = origFocalLengths[i];
         double reprojectionError = norm_L2(f0 * (p - measurements[k]));
         meanReprojectionError += reprojectionError;
      }
      cout << "mean reprojection error (in pixels): " << meanReprojectionError/K << endl;
   }

} // end namespace <>

int
main(int argc, char * argv[])
{
   if (argc != 3)
   {
      cerr << "Usage: " << argv[0] << " <sparse reconstruction file> <mode>" << endl;
      cout << "<mode> is one of metric, focal, prinipal, radial, tangental." << endl;
      return -1;
   }

   ifstream is(argv[1]);
   if (!is)
   {
      cerr << "Cannot open " << argv[1] << endl;
      return -2;
   }

   int mode = 0;
   if (strcmp(argv[2], "metric") == 0)
      mode = FULL_BUNDLE_METRIC;
   else if (strcmp(argv[2], "focal") == 0)
      mode = FULL_BUNDLE_FOCAL_LENGTH;
   else if (strcmp(argv[2], "principal") == 0)
      mode = FULL_BUNDLE_FOCAL_LENGTH_PP;
   else if (strcmp(argv[2], "radial") == 0)
      mode = FULL_BUNDLE_RADIAL;
   else if (strcmp(argv[2], "tangential") == 0)
      mode = FULL_BUNDLE_RADIAL_TANGENTIAL;
   else
   {
      cerr << "Unknown bundle mode: " << argv[2] << endl;
      return -2;
   }

   int N, M, K;
   is >> M >> N >> K;
   cout << "N (cams) = " << N << " M (points) = " << M << " K (measurements) = " << K << endl;

   vector<StdDistortionFunction> distortions(N);
   vector<double> origFocalLengths(N);
   vector<CameraMatrix> cams(N);

   double avgFocalLength = 0.0;

   for (int i = 0; i < N; ++i)
   {
      Matrix3x3d KMat;
      makeIdentityMatrix(KMat);
      is >> KMat[0][0] >> KMat[0][1] >> KMat[0][2] >> KMat[1][1] >> KMat[1][2]
         >> distortions[i].k1 >> distortions[i].k2 >> distortions[i].p1 >> distortions[i].p2;

      double const f0 = KMat[0][0];
      Matrix3x3d Knorm = KMat;
      // Normalize the intrinsic to have unit focal length.
      scaleMatrixIP(1.0/f0, Knorm);
      Knorm[2][2] = 1.0;

      origFocalLengths[i] = f0;
      cams[i].setIntrinsic(Knorm);
      avgFocalLength += f0;
   } // end for (i)

   avgFocalLength /= N;
   cout << "mean focal length = " << avgFocalLength << endl;

   vector<int> pointIdFwdMap(M);
   map<int, int> pointIdBwdMap;

   vector<Vector3d > Xs(M);
   for (int j = 0; j < M; ++j)
   {
      int pointId;
      is >> pointId >> Xs[j][0] >> Xs[j][1] >> Xs[j][2];
      pointIdFwdMap[j] = pointId;
      pointIdBwdMap.insert(make_pair(pointId, j));
   }
   cout << "Read the 3D points." << endl;

   vector<int> camIdFwdMap(N);
   map<int, int> camIdBwdMap;

   for (int i = 0; i < N; ++i)
   {
      int camId;
      Matrix3x3d R;
      Vector3d T;

      is >> camId;
      is >> R[0][0] >> R[0][1] >> R[0][2] >> T[0];
      is >> R[1][0] >> R[1][1] >> R[1][2] >> T[1];
      is >> R[2][0] >> R[2][1] >> R[2][2] >> T[2];

      camIdFwdMap[i] = camId;
      camIdBwdMap.insert(make_pair(camId, i));

#if 1
      cams[i].setRotation(R);
      cams[i].setTranslation(T);
#else
      cams[i].setRotation(transposedMatrix(R));
      cams[i].setTranslation(transposedMatrix(R) * (-1.0 * T));
#endif
   }
   cout << "Read the cameras." << endl;

   vector<Vector2d > measurements;
   vector<int> correspondingView;
   vector<int> correspondingPoint;

   measurements.reserve(K);
   correspondingView.reserve(K);
   correspondingPoint.reserve(K);

   for (int k = 0; k < K; ++k)
   {
      int view, point;
      Vector3d p, np;

      is >> view >> point;
      is >> p[0] >> p[1] >> p[2];

      if (camIdBwdMap.find(view) != camIdBwdMap.end() &&
          pointIdBwdMap.find(point) != pointIdBwdMap.end())
      {
         int const i = (*camIdBwdMap.find(view)).second;
         double const f0 = origFocalLengths[i];
         // Normalize the measurements to match the unit focal length.
         scaleVectorIP(1.0/f0, p);
         measurements.push_back(makeVector2(p[0], p[1]));
         correspondingView.push_back(camIdBwdMap[view]);
         correspondingPoint.push_back(pointIdBwdMap[point]);
      }
   } // end for (k)

   K = measurements.size();

   cout << "Read " << K << " valid 2D measurements." << endl;

   showErrorStatistics(origFocalLengths, distortions, cams, Xs,
                       measurements, correspondingView, correspondingPoint);

   V3D::optimizerVerbosenessLevel = 1;
   double const inlierThreshold = 2.0 / avgFocalLength;

   Matrix3x3d K0 = cams[0].getIntrinsic();
   cout << "K0 = "; displayMatrix(K0);

   VaryingInternalsMetricBundleOptimizer opt(mode, inlierThreshold, distortions, cams, Xs,
                                             measurements, correspondingView, correspondingPoint);
   opt.maxIterations = 50;
   opt.minimize();
   cout << "optimizer status = " << opt.status << endl;

   showErrorStatistics(origFocalLengths, distortions, cams, Xs,
                       measurements, correspondingView, correspondingPoint);

   ofstream os("refined.txt");

   os << M << " " << N << " " << K << endl;

   for (int i = 0; i < N; ++i)
   {
      Matrix3x3d Knew = cams[i].getIntrinsic();
      scaleMatrixIP(origFocalLengths[i], Knew);
      Knew[2][2] = 1.0;
      os << Knew[0][0] << " " << Knew[0][1] << " " << Knew[0][2] << " " << Knew[1][1] << " " << Knew[1][2] << " "
         << distortions[i].k1 << " " << distortions[i].k2 << " "
         << distortions[i].p1 << " " << distortions[i].p2 << " " << endl;
   }

   for (int j = 0; j < M; ++j)
   {
      os << pointIdFwdMap[j] << " " << Xs[j][0] << " " << Xs[j][1] << " " << Xs[j][2] << endl;
   }

   for (int i = 0; i < N; ++i)
   {
      os << camIdFwdMap[i] << " ";
      Matrix3x4d const RT = cams[i].getOrientation();
      os << RT[0][0] << " " << RT[0][1] << " " << RT[0][2] << " " << RT[0][3] << " ";
      os << RT[1][0] << " " << RT[1][1] << " " << RT[1][2] << " " << RT[1][3] << " ";
      os << RT[2][0] << " " << RT[2][1] << " " << RT[2][2] << " " << RT[2][3] << endl;
   }

   return 0;
}
<|endoftext|>


<commit_before>#include "curve_editor.h"

#include "halley/core/graphics/painter.h"

using namespace Halley;

CurveEditor::CurveEditor(String id, UIStyle _style)
	: UIWidget(std::move(id))
{
	styles.push_back(std::move(_style));
	setInteractWithMouse(true);

	const auto& style = styles.back();
	background = style.getSprite("background");
	display = style.getSprite("display");
	lineColour = style.getColour("lineColour");
	gridLine = style.getSprite("gridLine");
	tooltipLabel = style.getTextRenderer("tooltipLabel");
}

void CurveEditor::update(Time time, bool moved)
{
	if (!dragging && !isMouseOver()) {
		curAnchor = {};
		mouseAnchor = {};
		tooltipLabel.setText("");
	}

	if (moved) {
		const auto drawArea = getDrawArea();
		background.setPosition(getPosition()).scaleTo(getSize());
		display.setPos(drawArea.getTopLeft()).scaleTo(drawArea.getSize());
	}
}

void CurveEditor::draw(UIPainter& painter) const
{
	painter.draw(background);
	painter.draw(display);

	// Horizontal grid
	const auto drawArea = getDrawArea();
	const auto vLine = gridLine.clone().scaleTo(Vector2f(1, drawArea.getHeight()));
	for (size_t i = 0; i <= nHorizontalDividers; ++i) {
		float t = static_cast<float>(i) / static_cast<float>(nHorizontalDividers);
		painter.draw(vLine.clone().setPosition(lerp(drawArea.getTopLeft(), drawArea.getTopRight(), t)), true);
	}

	// Vertical grid
	const auto hLine = gridLine.clone().scaleTo(Vector2f(drawArea.getWidth(), 1));
	for (size_t i = 0; i <= nVerticalDividers; ++i) {
		float t = static_cast<float>(i) / static_cast<float>(nVerticalDividers);
		painter.draw(hLine.clone().setPosition(lerp(drawArea.getTopLeft(), drawArea.getBottomLeft(), t)), true);
	}

	painter.draw([this] (Painter& painter)
	{
		Vector<Vector2f> ps;
		ps.resize(points.size());

		for (size_t i = 0; i < points.size(); ++i) {
			ps[i] = curveToMouseSpace(points[i]);
		}

		painter.drawLine(ps, 1.0f, lineColour, false);

		for (size_t i = 0; i < points.size(); ++i) {
			drawAnchor(painter, ps[i], curAnchor == i);
		}

		if (mouseAnchor) {
			painter.drawCircle(curveToMouseSpace(*mouseAnchor), 1.5f, 3.0f, lineColour);
		}
	});
	painter.draw(tooltipLabel);
}

void CurveEditor::setHorizontalRange(Range<float> range)
{
	horizontalRange = range;
	normalizePoints();
}

Range<float> CurveEditor::getHorizontalRange() const
{
	return horizontalRange;
}

void CurveEditor::setHorizontalDividers(size_t n)
{
	nHorizontalDividers = n;
}

void CurveEditor::setVerticalDividers(size_t n)
{
	nVerticalDividers = n;
}

void CurveEditor::setPoints(Vector<Vector2f> pts)
{
	points = std::move(pts);
	normalizePoints();
}

const Vector<Vector2f>& CurveEditor::getPoints() const
{
	return points;
}

Vector<Vector2f>& CurveEditor::getPoints()
{
	return points;
}

void CurveEditor::setChangeCallback(Callback callback)
{
	this->callback = std::move(callback);
}

void CurveEditor::onMouseOver(Vector2f mousePos)
{
	if (!dragging) {
		curAnchor = getAnchorAt(mousePos);
	}
	updateDragging(mousePos);

	if (curAnchor) {
		mouseAnchor = {};
	} else {
		mouseAnchor = clampPoint(mouseToCurveSpace(mousePos));
	}

	const auto drawArea = getDrawArea();
	const bool left = mousePos.x > drawArea.getCenter().x;
	const auto curPos = curAnchor ? points[*curAnchor] : *mouseAnchor;
	tooltipLabel
		.setOffset(Vector2f(left ? 0.0f : 1.0f, 0.0f))
		.setPosition(left ? drawArea.getTopLeft() : drawArea.getTopRight())
		.setText(toString(curPos.x, 2) + ", " + toString(curPos.y, 2));
}

void CurveEditor::pressMouse(Vector2f mousePos, int button, KeyMods keyMods)
{
	if (button == 0) {
		const auto anchor = getAnchorAt(mousePos);
		curAnchor = anchor;
		if (anchor) {
			dragging = true;
			updateDragging(mousePos);
		} else {
			insertPoint(mouseToCurveSpace(mousePos));
		}
	}

	if (button == 2) {
		const auto anchor = getAnchorAt(mousePos);
		if (anchor) {
			deletePoint(anchor.value());
		}
	}
}

void CurveEditor::releaseMouse(Vector2f mousePos, int button)
{
	if (button == 0) {
		if (dragging) {
			dragging = false;
		}
	}
}

bool CurveEditor::isFocusLocked() const
{
	return dragging;
}

bool CurveEditor::canReceiveFocus() const
{
	return true;
}

void CurveEditor::normalizePoints()
{
	auto startPoints = points;

	if (points.empty()) {
		points.push_back(Vector2f(horizontalRange.start, 0));
		points.push_back(Vector2f(horizontalRange.end, 1));
	}
	if (points.size() == 1) {
		points.push_back(points.back());
	}
	points.front().x = horizontalRange.start;
	points.back().x = horizontalRange.end;

	for (auto& p: points) {
		p = clampPoint(p);
	}

	if (points != startPoints) {
		notifyChange();
	}
}

void CurveEditor::notifyChange()
{
	if (callback) {
		callback(points);
	}
}

Rect4f CurveEditor::getDrawArea() const
{
	return Rect4f(getPosition(), getPosition() + getSize()).shrink(5);
}

void CurveEditor::drawAnchor(Painter& painter, Vector2f pos, bool highlighted) const
{
	painter.drawCircle(pos, 2.0f, highlighted ? 5.0f : 4.0f, highlighted ? lineColour.inverseMultiplyLuma(0.5f) : lineColour);
}

Vector2f CurveEditor::curveToMouseSpace(Vector2f curvePos) const
{
	const auto drawArea = getDrawArea();
	const Vector2f curveOrigin = Vector2f(horizontalRange.start, 0);
	const Vector2f curveScale = Vector2f(1.0f / horizontalRange.getLength(), -1.0f) * drawArea.getSize();

	return (curvePos - curveOrigin) * curveScale + drawArea.getBottomLeft();
}

Vector2f CurveEditor::mouseToCurveSpace(Vector2f mousePos) const
{
	const auto drawArea = getDrawArea();
	const Vector2f curveOrigin = Vector2f(horizontalRange.start, 0);
	const Vector2f curveScale = Vector2f(1.0f / horizontalRange.getLength(), -1.0f) * drawArea.getSize();

	return (mousePos - drawArea.getBottomLeft()) / curveScale + curveOrigin;
}

std::optional<size_t> CurveEditor::getAnchorAt(Vector2f mousePos) const
{
	float bestDist = 6.0f;
	std::optional<size_t> bestIdx;

	for (size_t i = 0; i < points.size(); ++i) {
		const auto pos = curveToMouseSpace(points[i]);
		const float dist = (pos - mousePos).length();
		if (dist < bestDist) {
			bestDist = dist;
			bestIdx = i;
		}
	}

	return bestIdx;
}

Vector2f CurveEditor::clampPoint(Vector2f p) const
{
	p.x = clamp(p.x, horizontalRange.start, horizontalRange.end);
	p.y = clamp(p.y, 0.0f, 1.0f);
	return p;
}

void CurveEditor::insertPoint(Vector2f curvePos)
{
	const auto pos = clampPoint(curvePos);

	for (size_t i = 0; i < points.size() - 1; ++i) {
		if (points[i].x > pos.x) {
			points.insert(points.begin() + i, pos);
			curAnchor = i;
			dragging = true;
			notifyChange();
			return;
		}
	}

	const auto idx = points.size() - 1;
	points.insert(points.begin() + idx, pos);
	curAnchor = idx;
	dragging = true;
	notifyChange();
}

void CurveEditor::deletePoint(size_t idx)
{
	if (idx > 0 && idx < points.size() - 1) {
		points.erase(points.begin() + idx);
		notifyChange();
	}
}

void CurveEditor::updateDragging(Vector2f mousePos)
{
	if (dragging && curAnchor) {
		const auto idx = curAnchor.value();

		points[idx] = mouseToCurveSpace(mousePos);
		normalizePoints();

		if (idx > 0 && points[idx].x < points[idx - 1].x) {
			std::swap(points[idx], points[idx - 1]);
			curAnchor = idx - 1;
		}

		if (idx < points.size() - 1 && points[idx].x > points[idx + 1].x) {
			std::swap(points[idx], points[idx + 1]);
			curAnchor = idx + 1;
		}

		notifyChange();
	}
}
<commit_msg>Remap points when changing horizontal range of curve<commit_after>#include "curve_editor.h"

#include "halley/core/graphics/painter.h"

using namespace Halley;

CurveEditor::CurveEditor(String id, UIStyle _style)
	: UIWidget(std::move(id))
{
	styles.push_back(std::move(_style));
	setInteractWithMouse(true);

	const auto& style = styles.back();
	background = style.getSprite("background");
	display = style.getSprite("display");
	lineColour = style.getColour("lineColour");
	gridLine = style.getSprite("gridLine");
	tooltipLabel = style.getTextRenderer("tooltipLabel");
}

void CurveEditor::update(Time time, bool moved)
{
	if (!dragging && !isMouseOver()) {
		curAnchor = {};
		mouseAnchor = {};
		tooltipLabel.setText("");
	}

	if (moved) {
		const auto drawArea = getDrawArea();
		background.setPosition(getPosition()).scaleTo(getSize());
		display.setPos(drawArea.getTopLeft()).scaleTo(drawArea.getSize());
	}
}

void CurveEditor::draw(UIPainter& painter) const
{
	painter.draw(background);
	painter.draw(display);

	// Horizontal grid
	const auto drawArea = getDrawArea();
	const auto vLine = gridLine.clone().scaleTo(Vector2f(1, drawArea.getHeight()));
	for (size_t i = 0; i <= nHorizontalDividers; ++i) {
		float t = static_cast<float>(i) / static_cast<float>(nHorizontalDividers);
		painter.draw(vLine.clone().setPosition(lerp(drawArea.getTopLeft(), drawArea.getTopRight(), t)), true);
	}

	// Vertical grid
	const auto hLine = gridLine.clone().scaleTo(Vector2f(drawArea.getWidth(), 1));
	for (size_t i = 0; i <= nVerticalDividers; ++i) {
		float t = static_cast<float>(i) / static_cast<float>(nVerticalDividers);
		painter.draw(hLine.clone().setPosition(lerp(drawArea.getTopLeft(), drawArea.getBottomLeft(), t)), true);
	}

	painter.draw([this] (Painter& painter)
	{
		Vector<Vector2f> ps;
		ps.resize(points.size());

		for (size_t i = 0; i < points.size(); ++i) {
			ps[i] = curveToMouseSpace(points[i]);
		}

		painter.drawLine(ps, 1.0f, lineColour, false);

		for (size_t i = 0; i < points.size(); ++i) {
			drawAnchor(painter, ps[i], curAnchor == i);
		}

		if (mouseAnchor) {
			painter.drawCircle(curveToMouseSpace(*mouseAnchor), 1.5f, 3.0f, lineColour);
		}
	});
	painter.draw(tooltipLabel);
}

void CurveEditor::setHorizontalRange(Range<float> range)
{
	for (auto& p: points) {
		p.x = lerp(range.start, range.end, invLerp(p.x, horizontalRange.start, horizontalRange.end));
	}

	horizontalRange = range;
	normalizePoints();
}

Range<float> CurveEditor::getHorizontalRange() const
{
	return horizontalRange;
}

void CurveEditor::setHorizontalDividers(size_t n)
{
	nHorizontalDividers = n;
}

void CurveEditor::setVerticalDividers(size_t n)
{
	nVerticalDividers = n;
}

void CurveEditor::setPoints(Vector<Vector2f> pts)
{
	points = std::move(pts);
	normalizePoints();
}

const Vector<Vector2f>& CurveEditor::getPoints() const
{
	return points;
}

Vector<Vector2f>& CurveEditor::getPoints()
{
	return points;
}

void CurveEditor::setChangeCallback(Callback callback)
{
	this->callback = std::move(callback);
}

void CurveEditor::onMouseOver(Vector2f mousePos)
{
	if (!dragging) {
		curAnchor = getAnchorAt(mousePos);
	}
	updateDragging(mousePos);

	if (curAnchor) {
		mouseAnchor = {};
	} else {
		mouseAnchor = clampPoint(mouseToCurveSpace(mousePos));
	}

	const auto drawArea = getDrawArea();
	const bool left = mousePos.x > drawArea.getCenter().x;
	const auto curPos = curAnchor ? points[*curAnchor] : *mouseAnchor;
	tooltipLabel
		.setOffset(Vector2f(left ? 0.0f : 1.0f, 0.0f))
		.setPosition(left ? drawArea.getTopLeft() : drawArea.getTopRight())
		.setText(toString(curPos.x, 2) + ", " + toString(curPos.y, 2));
}

void CurveEditor::pressMouse(Vector2f mousePos, int button, KeyMods keyMods)
{
	if (button == 0) {
		const auto anchor = getAnchorAt(mousePos);
		curAnchor = anchor;
		if (anchor) {
			dragging = true;
			updateDragging(mousePos);
		} else {
			insertPoint(mouseToCurveSpace(mousePos));
		}
	}

	if (button == 2) {
		const auto anchor = getAnchorAt(mousePos);
		if (anchor) {
			deletePoint(anchor.value());
		}
	}
}

void CurveEditor::releaseMouse(Vector2f mousePos, int button)
{
	if (button == 0) {
		if (dragging) {
			dragging = false;
		}
	}
}

bool CurveEditor::isFocusLocked() const
{
	return dragging;
}

bool CurveEditor::canReceiveFocus() const
{
	return true;
}

void CurveEditor::normalizePoints()
{
	auto startPoints = points;

	if (points.empty()) {
		points.push_back(Vector2f(horizontalRange.start, 0));
		points.push_back(Vector2f(horizontalRange.end, 1));
	}
	if (points.size() == 1) {
		points.push_back(points.back());
	}
	points.front().x = horizontalRange.start;
	points.back().x = horizontalRange.end;

	for (auto& p: points) {
		p = clampPoint(p);
	}

	if (points != startPoints) {
		notifyChange();
	}
}

void CurveEditor::notifyChange()
{
	if (callback) {
		callback(points);
	}
}

Rect4f CurveEditor::getDrawArea() const
{
	return Rect4f(getPosition(), getPosition() + getSize()).shrink(5);
}

void CurveEditor::drawAnchor(Painter& painter, Vector2f pos, bool highlighted) const
{
	painter.drawCircle(pos, 2.0f, highlighted ? 5.0f : 4.0f, highlighted ? lineColour.inverseMultiplyLuma(0.5f) : lineColour);
}

Vector2f CurveEditor::curveToMouseSpace(Vector2f curvePos) const
{
	const auto drawArea = getDrawArea();
	const Vector2f curveOrigin = Vector2f(horizontalRange.start, 0);
	const Vector2f curveScale = Vector2f(1.0f / horizontalRange.getLength(), -1.0f) * drawArea.getSize();

	return (curvePos - curveOrigin) * curveScale + drawArea.getBottomLeft();
}

Vector2f CurveEditor::mouseToCurveSpace(Vector2f mousePos) const
{
	const auto drawArea = getDrawArea();
	const Vector2f curveOrigin = Vector2f(horizontalRange.start, 0);
	const Vector2f curveScale = Vector2f(1.0f / horizontalRange.getLength(), -1.0f) * drawArea.getSize();

	return (mousePos - drawArea.getBottomLeft()) / curveScale + curveOrigin;
}

std::optional<size_t> CurveEditor::getAnchorAt(Vector2f mousePos) const
{
	float bestDist = 6.0f;
	std::optional<size_t> bestIdx;

	for (size_t i = 0; i < points.size(); ++i) {
		const auto pos = curveToMouseSpace(points[i]);
		const float dist = (pos - mousePos).length();
		if (dist < bestDist) {
			bestDist = dist;
			bestIdx = i;
		}
	}

	return bestIdx;
}

Vector2f CurveEditor::clampPoint(Vector2f p) const
{
	p.x = clamp(p.x, horizontalRange.start, horizontalRange.end);
	p.y = clamp(p.y, 0.0f, 1.0f);
	return p;
}

void CurveEditor::insertPoint(Vector2f curvePos)
{
	const auto pos = clampPoint(curvePos);

	for (size_t i = 0; i < points.size() - 1; ++i) {
		if (points[i].x > pos.x) {
			points.insert(points.begin() + i, pos);
			curAnchor = i;
			dragging = true;
			notifyChange();
			return;
		}
	}

	const auto idx = points.size() - 1;
	points.insert(points.begin() + idx, pos);
	curAnchor = idx;
	dragging = true;
	notifyChange();
}

void CurveEditor::deletePoint(size_t idx)
{
	if (idx > 0 && idx < points.size() - 1) {
		points.erase(points.begin() + idx);
		notifyChange();
	}
}

void CurveEditor::updateDragging(Vector2f mousePos)
{
	if (dragging && curAnchor) {
		const auto idx = curAnchor.value();

		points[idx] = mouseToCurveSpace(mousePos);
		normalizePoints();

		if (idx > 0 && points[idx].x < points[idx - 1].x) {
			std::swap(points[idx], points[idx - 1]);
			curAnchor = idx - 1;
		}

		if (idx < points.size() - 1 && points[idx].x > points[idx + 1].x) {
			std::swap(points[idx], points[idx + 1]);
			curAnchor = idx + 1;
		}

		notifyChange();
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2011-2018 The Syscoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <qt/qrimagewidget.h>

#include <qt/guiutil.h>

#include <QApplication>
#include <QClipboard>
#include <QDrag>
#include <QMenu>
#include <QMimeData>
#include <QMouseEvent>
#include <QPainter>

#if defined(HAVE_CONFIG_H)
#include <config/syscoin-config.h> /* for USE_QRCODE */
#endif

#ifdef USE_QRCODE
#include <qrencode.h>
#endif

QRImageWidget::QRImageWidget(QWidget *parent):
    QLabel(parent), contextMenu(nullptr)
{
    contextMenu = new QMenu(this);
    QAction *saveImageAction = new QAction(tr("&Save Image..."), this);
    connect(saveImageAction, &QAction::triggered, this, &QRImageWidget::saveImage);
    contextMenu->addAction(saveImageAction);
    QAction *copyImageAction = new QAction(tr("&Copy Image"), this);
    connect(copyImageAction, &QAction::triggered, this, &QRImageWidget::copyImage);
    contextMenu->addAction(copyImageAction);
}

bool QRImageWidget::setQR(const QString& data, const QString& text)
{
#ifdef USE_QRCODE
    setText("");
    if (data.isEmpty()) return false;

    // limit length
    if (data.length() > MAX_URI_LENGTH) {
        setText(tr("Resulting URI too long, try to reduce the text for label / message."));
        return false;
    }

    QRcode *code = QRcode_encodeString(data.toUtf8().constData(), 0, QR_ECLEVEL_L, QR_MODE_8, 1);

    if (!code) {
        setText(tr("Error encoding URI into QR Code."));
        return false;
    }

    QImage qrImage = QImage(code->width + 8, code->width + 8, QImage::Format_RGB32);
    qrImage.fill(0xffffff);
    unsigned char *p = code->data;
    for (int y = 0; y < code->width; ++y) {
        for (int x = 0; x < code->width; ++x) {
            qrImage.setPixel(x + 4, y + 4, ((*p & 1) ? 0x0 : 0xffffff));
            ++p;
        }
    }
    QRcode_free(code);

    QImage qrAddrImage = QImage(QR_IMAGE_SIZE, QR_IMAGE_SIZE + (text.isEmpty() ? 0 : 20), QImage::Format_RGB32);
    qrAddrImage.fill(0xffffff);
    QPainter painter(&qrAddrImage);
    painter.drawImage(0, 0, qrImage.scaled(QR_IMAGE_SIZE, QR_IMAGE_SIZE));

    if (!text.isEmpty()) {
        QFont font = GUIUtil::fixedPitchFont();
        QRect paddedRect = qrAddrImage.rect();

        // calculate ideal font size
        qreal font_size = GUIUtil::calculateIdealFontSize(paddedRect.width() - 20, text, font);
        font.setPointSizeF(font_size);

        painter.setFont(font);
        paddedRect.setHeight(QR_IMAGE_SIZE+12);
        painter.drawText(paddedRect, Qt::AlignBottom|Qt::AlignCenter, text);
    }

    painter.end();
    setPixmap(QPixmap::fromImage(qrAddrImage));

    return true;
#else
    setText(tr("QR code support not available."));
    return false;
#endif
}

QImage QRImageWidget::exportImage()
{
    if(!pixmap())
        return QImage();
    return pixmap()->toImage();
}

void QRImageWidget::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton && pixmap())
    {
        event->accept();
        QMimeData *mimeData = new QMimeData;
        mimeData->setImageData(exportImage());

        QDrag *drag = new QDrag(this);
        drag->setMimeData(mimeData);
        drag->exec();
    } else {
        QLabel::mousePressEvent(event);
    }
}

void QRImageWidget::saveImage()
{
    if(!pixmap())
        return;
    QString fn = GUIUtil::getSaveFileName(this, tr("Save QR Code"), QString(), tr("PNG Image (*.png)"), nullptr);
    if (!fn.isEmpty())
    {
        exportImage().save(fn);
    }
}

void QRImageWidget::copyImage()
{
    if(!pixmap())
        return;
    QApplication::clipboard()->setImage(exportImage());
}

void QRImageWidget::contextMenuEvent(QContextMenuEvent *event)
{
    if(!pixmap())
        return;
    contextMenu->exec(event->globalPos());
}
<commit_msg>gui: disable font antialiasing for QR image address<commit_after>// Copyright (c) 2011-2018 The Syscoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <qt/qrimagewidget.h>

#include <qt/guiutil.h>

#include <QApplication>
#include <QClipboard>
#include <QDrag>
#include <QMenu>
#include <QMimeData>
#include <QMouseEvent>
#include <QPainter>

#if defined(HAVE_CONFIG_H)
#include <config/syscoin-config.h> /* for USE_QRCODE */
#endif

#ifdef USE_QRCODE
#include <qrencode.h>
#endif

QRImageWidget::QRImageWidget(QWidget *parent):
    QLabel(parent), contextMenu(nullptr)
{
    contextMenu = new QMenu(this);
    QAction *saveImageAction = new QAction(tr("&Save Image..."), this);
    connect(saveImageAction, &QAction::triggered, this, &QRImageWidget::saveImage);
    contextMenu->addAction(saveImageAction);
    QAction *copyImageAction = new QAction(tr("&Copy Image"), this);
    connect(copyImageAction, &QAction::triggered, this, &QRImageWidget::copyImage);
    contextMenu->addAction(copyImageAction);
}

bool QRImageWidget::setQR(const QString& data, const QString& text)
{
#ifdef USE_QRCODE
    setText("");
    if (data.isEmpty()) return false;

    // limit length
    if (data.length() > MAX_URI_LENGTH) {
        setText(tr("Resulting URI too long, try to reduce the text for label / message."));
        return false;
    }

    QRcode *code = QRcode_encodeString(data.toUtf8().constData(), 0, QR_ECLEVEL_L, QR_MODE_8, 1);

    if (!code) {
        setText(tr("Error encoding URI into QR Code."));
        return false;
    }

    QImage qrImage = QImage(code->width + 8, code->width + 8, QImage::Format_RGB32);
    qrImage.fill(0xffffff);
    unsigned char *p = code->data;
    for (int y = 0; y < code->width; ++y) {
        for (int x = 0; x < code->width; ++x) {
            qrImage.setPixel(x + 4, y + 4, ((*p & 1) ? 0x0 : 0xffffff));
            ++p;
        }
    }
    QRcode_free(code);

    QImage qrAddrImage = QImage(QR_IMAGE_SIZE, QR_IMAGE_SIZE + (text.isEmpty() ? 0 : 20), QImage::Format_RGB32);
    qrAddrImage.fill(0xffffff);
    QPainter painter(&qrAddrImage);
    painter.drawImage(0, 0, qrImage.scaled(QR_IMAGE_SIZE, QR_IMAGE_SIZE));

    if (!text.isEmpty()) {
        QFont font = GUIUtil::fixedPitchFont();
        font.setStyleStrategy(QFont::NoAntialias);
        QRect paddedRect = qrAddrImage.rect();

        // calculate ideal font size
        qreal font_size = GUIUtil::calculateIdealFontSize(paddedRect.width() - 20, text, font);
        font.setPointSizeF(font_size);

        painter.setFont(font);
        paddedRect.setHeight(QR_IMAGE_SIZE+12);
        painter.drawText(paddedRect, Qt::AlignBottom|Qt::AlignCenter, text);
    }

    painter.end();
    setPixmap(QPixmap::fromImage(qrAddrImage));

    return true;
#else
    setText(tr("QR code support not available."));
    return false;
#endif
}

QImage QRImageWidget::exportImage()
{
    if(!pixmap())
        return QImage();
    return pixmap()->toImage();
}

void QRImageWidget::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton && pixmap())
    {
        event->accept();
        QMimeData *mimeData = new QMimeData;
        mimeData->setImageData(exportImage());

        QDrag *drag = new QDrag(this);
        drag->setMimeData(mimeData);
        drag->exec();
    } else {
        QLabel::mousePressEvent(event);
    }
}

void QRImageWidget::saveImage()
{
    if(!pixmap())
        return;
    QString fn = GUIUtil::getSaveFileName(this, tr("Save QR Code"), QString(), tr("PNG Image (*.png)"), nullptr);
    if (!fn.isEmpty())
    {
        exportImage().save(fn);
    }
}

void QRImageWidget::copyImage()
{
    if(!pixmap())
        return;
    QApplication::clipboard()->setImage(exportImage());
}

void QRImageWidget::contextMenuEvent(QContextMenuEvent *event)
{
    if(!pixmap())
        return;
    contextMenu->exec(event->globalPos());
}
<|endoftext|>


<commit_before>/**
 * This file is part of the "FnordMetric" project
 *   Copyright (c) 2014 Paul Asmuth, Google Inc.
 *
 * Licensed under the MIT license (see LICENSE).
 */
#include <stdlib.h>
#include <assert.h>
#include <string>
#include <unordered_map>
#include "symboltable.h"

namespace fnordmetric {
namespace query {

static std::unordered_map<std::string, const SymbolTableEntry*> global_symbols_;

const SymbolTableEntry* lookupSymbol(const std::string& symbol) {
  auto iter = global_symbols_.find(symbol);

  if (iter == global_symbols_.end()) {
    return nullptr;
  } else {
    return iter->second;
  }
}

SymbolTableEntry::SymbolTableEntry(
    const std::string& symbol,
    void (*method)(void*, int, SValue*, SValue*),
    size_t scratchpad_size) :
    call_(method),
    scratchpad_size_(scratchpad_size) {
  assert(global_symbols_.find(symbol) == global_symbols_.end());
  global_symbols_[symbol] = this;
}

SymbolTableEntry::SymbolTableEntry(
    const std::string& symbol,
    void (*method)(void*, int, SValue*, SValue*)) :
    SymbolTableEntry(symbol, method, 0) {}

bool SymbolTableEntry::isAggregate() const {
  return scratchpad_size_ > 0;
}

void (*SymbolTableEntry::getFnPtr() const)(void*, int, SValue*, SValue*) {
  return call_;
}

size_t SymbolTableEntry::getScratchpadSize() const {
  return scratchpad_size_;
}

}
}
<commit_msg>fix cross compilation unit global symbol table<commit_after>/**
 * This file is part of the "FnordMetric" project
 *   Copyright (c) 2014 Paul Asmuth, Google Inc.
 *
 * Licensed under the MIT license (see LICENSE).
 */
#include <stdlib.h>
#include <assert.h>
#include <string>
#include <unordered_map>
#include "symboltable.h"

namespace fnordmetric {
namespace query {

static std::unordered_map<std::string, const SymbolTableEntry*>*
  __globalSymbolTable() {
  static std::unordered_map<std::string, const SymbolTableEntry*> symbols;
  return &symbols;
}

const SymbolTableEntry* lookupSymbol(const std::string& symbol) {
  auto iter = __globalSymbolTable()->find(symbol);

  if (iter == __globalSymbolTable()->end()) {
    return nullptr;
  } else {
    return iter->second;
  }
}

SymbolTableEntry::SymbolTableEntry(
    const std::string& symbol,
    void (*method)(void*, int, SValue*, SValue*),
    size_t scratchpad_size) :
    call_(method),
    scratchpad_size_(scratchpad_size) {
  assert(__globalSymbolTable()->find(symbol) == __globalSymbolTable()->end());
  (*__globalSymbolTable())[symbol] = this;
}

SymbolTableEntry::SymbolTableEntry(
    const std::string& symbol,
    void (*method)(void*, int, SValue*, SValue*)) :
    SymbolTableEntry(symbol, method, 0) {}

bool SymbolTableEntry::isAggregate() const {
  return scratchpad_size_ > 0;
}

void (*SymbolTableEntry::getFnPtr() const)(void*, int, SValue*, SValue*) {
  return call_;
}

size_t SymbolTableEntry::getScratchpadSize() const {
  return scratchpad_size_;
}

}
}
<|endoftext|>


<commit_before>#ifndef GRAMMAR_PRODUCTION_HPP
#define GRAMMAR_PRODUCTION_HPP

#include <list>

#include "grammar/non_terminal.hpp"

namespace grammar
{

class production
{
public:
    production();
    production(non_terminal* from, std::initializer_list<symbol*> to = {});

    bool initialized() const;

private:
    non_terminal* m_from;
    std::list<symbol*> m_to;
};

};

#endif /* GRAMMAR_PRODUCTION_HPP */
<commit_msg>Use forward decl.<commit_after>#ifndef GRAMMAR_PRODUCTION_HPP
#define GRAMMAR_PRODUCTION_HPP

#include <list>

namespace grammar
{

class non_terminal;
class symbol;

class production
{
public:
    production();
    production(non_terminal* from, std::initializer_list<symbol*> to = {});

    bool initialized() const;

private:
    non_terminal* m_from;
    std::list<symbol*> m_to;
};

}

#endif /* GRAMMAR_PRODUCTION_HPP */
<|endoftext|>