<commit_before>/*********************************************************************************[Normalization.C]
Copyright (c) 2008, Niklas Sorensson

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************************************/

#include "mtl/Sort.h"
#include "mtl/Alg.h"
#include "circ/Normalization.h"

using namespace Minisat;

//=================================================================================================
// Normalization functions for different n-ary gate types:

void Minisat::normalizeXors(vec<Sig>& xs)
{
    // Calculate the parity and make inputs unsigned:
    //
    bool pol = false;
    for (int i = 0; i < xs.size(); i++){
        pol   = pol ^ sign(xs[i]);
        xs[i] = mkSig(gate(xs[i]));
    }

    // Sort and remove duplicates properly:
    //
    int  i, j, k;
    sort(xs);
    for (i = j = 0; i < xs.size(); i = k){
        // Check how many times xs[i] is repeated:
        for (k = i; k < xs.size() && xs[k] == xs[i]; k++)
            ;

        // fprintf(stderr, "i = %d, j = %d, k = %d, k - i = %d\n", i, j, k, k - i);

        // Only if xs[i] occurs an odd number of times it should be kept:
        if ((k - i) % 2 == 1)
            xs[j++] = xs[i];
    }
    xs.shrink(i - j);

    // Remove possible remaining constant (can only be one, and it must occur first):
    if (xs.size() > 0 && xs[0] == sig_True){
        for (i = 1; i < xs.size(); i++)
            xs[i-1] = xs[i];
        xs.shrink(1);
        pol = !pol;
    }

    if (xs.size() > 0)
        // Attach the sign to the last element:
        xs.last() = xs.last() ^ pol;
    else if (pol)
        // If the xor-chain is empty but the output is expected to be negated, add a constant true:
        xs.push(sig_True);
}

void Minisat::normalizeAnds(vec<Sig>& xs)
{
    int  i, j;
    sort(xs);

    // Remove duplicates and detect inconsistencies:
    for (i = j = 1; i < xs.size(); i++)
        if (xs[i] == ~xs[j-1]){
            xs.clear();
            xs.push(sig_False);
            return;
        }else if (xs[i] != xs[j-1])
            xs[j++] = xs[i];

    xs.shrink(i - j);

    // Remove constant true:
    if (xs.size() > 0 && xs[0] == sig_True){
        for (i = 1; i < xs.size(); i++)
            xs[i-1] = xs[i];
        xs.shrink(1);
    }

    // Detect constant false:
    if (xs.size() > 0 && xs[0] == sig_False){
        xs.clear();
        xs.push(sig_False);
    }
}

void Minisat::normalizeOrs(vec<Sig>& xs)
{
    int  i, j;
    sort(xs);

    // Remove duplicates and detect tautologies:
    for (i = j = 1; i < xs.size(); i++)
        if (xs[i] == ~xs[j-1]){
            xs.clear();
            xs.push(sig_True);
            return;
        }else if (xs[i] != xs[j-1])
            xs[j++] = xs[i];

    xs.shrink(i - j);

    // Detect constant true:
    if (xs.size() > 0 && xs[0] == sig_True){
        xs.clear();
        xs.push(sig_True);
    }

    // Remove constant false:
    if (xs.size() > 0 && xs[0] == sig_False){
        for (i = 1; i < xs.size(); i++)
            xs[i-1] = xs[i];
        xs.shrink(1);
    }
}

// Shamelessly stolen from "SolverTypes.h" ...
static inline Sig subsumes(const vec<Sig>& xs, const vec<Sig>& ys)
{
    if (ys.size() < xs.size())
        return sig_Error;

    Sig ret = sig_Undef;
    for (int i = 0; i < xs.size(); i++){
        // search for xs[i] or ~xs[i]
        for (int j = 0; j < ys.size(); j++)
            if (xs[i] == ys[j])
                goto ok;
            else if (ret == sig_Undef && xs[i] == ~ys[j]){
                ret = ys[j];
                goto ok;
            }

        // did not find it
        return sig_Error;
    ok:;
    }

    return ret;
}

static void printSigs(const vec<Sig>& xs)
{
    fprintf(stderr, "{ ");
    for (int i = 0; i < xs.size(); i++)
        fprintf(stderr, "%s%s%d ", sign(xs[i])?"-":"", type(xs[i]) == gtype_Inp ? "$" : "@", index(gate(xs[i])));
    fprintf(stderr, "}");
}

const vec<vec<Sig> > Minisat::empty_context;

static void subsumptionResolutionSaturation(vec<vec<Sig> >& xss, const vec<vec<Sig> >& context = empty_context)
{
    // fprintf(stderr, "STARTING SUBSUMPTION RESULTION:\n");
    // for (int i = 0; i < xss.size(); i++){
    //     fprintf(stderr, " --- ");
    //     printSigs(xss[i]);
    //     fprintf(stderr, "\n");
    // }
    vec<Sig> tmp;

    // INVARIANT: xs[0] .. xs[i] is normalized.
    //
    for (int i = 0; i < xss.size(); i++){
        // fprintf(stderr, "PROCESSING (i = %d, xss.length = %d)\n", i, xss.size());

        // Check contextual forwards subsumption:
        for (int j = 0; j < context.size(); j++){
            Sig sub_result = subsumes(context[j], xss[i]);

            if (sub_result == sig_Undef){
                // fprintf(stderr, "FWD-CTX-SUB (i = %d, j = %d)\n", i, j);
                // fprintf(stderr, " >>> (i) "); printSigs(xss[i]); fprintf(stderr, "\n");
                // fprintf(stderr, " >>> (j) "); printSigs(context[j]); fprintf(stderr, "\n");
                xss.last().moveTo(xss[i]);
                xss.pop();
                i--;
                goto next_i;
            }else if (sub_result != sig_Error){
                // fprintf(stderr, "FWD-CTX-SUB-RES (i = %d, j = %d)\n", i, j);
                // fprintf(stderr, " >>> (i) "); printSigs(xss[i]); fprintf(stderr, "\n");
                // fprintf(stderr, " >>> (j) "); printSigs(context[j]); fprintf(stderr, "\n");
                remove(xss[i], sub_result);
            }
        }

        // Check forwards subsumption:
        for (int j = 0; j < i; j++){
            Sig sub_result = subsumes(xss[j], xss[i]);

            if (sub_result == sig_Undef){
                // fprintf(stderr, "FWD-SUB (i = %d, j = %d)\n", i, j);
                // fprintf(stderr, " >>> (i) "); printSigs(xss[i]); fprintf(stderr, "\n");
                // fprintf(stderr, " >>> (j) "); printSigs(xss[j]); fprintf(stderr, "\n");
                xss.last().moveTo(xss[i]);
                xss.pop();
                i--;
                goto next_i;
            }else if (sub_result != sig_Error){
                // fprintf(stderr, "FWD-SUB-RES (i = %d, j = %d)\n", i, j);
                // fprintf(stderr, " >>> (i) "); printSigs(xss[i]); fprintf(stderr, "\n");
                // fprintf(stderr, " >>> (j) "); printSigs(xss[j]); fprintf(stderr, "\n");
                remove(xss[i], sub_result);
            }
        }

        // Check backwards subsumption:
        for (int j = 0; j < i; j++){
            Sig sub_result = subsumes(xss[i], xss[j]);

            if (sub_result == sig_Undef){
                // fprintf(stderr, "BWD-SUB (i = %d, j = %d)\n", i, j);
                // fprintf(stderr, " >>> (i) "); printSigs(xss[i]); fprintf(stderr, "\n");
                // fprintf(stderr, " >>> (j) "); printSigs(xss[j]); fprintf(stderr, "\n");
                xss[i-1].moveTo(xss[j]);
                xss[i].moveTo(xss[i-1]);
                xss.last().moveTo(xss[i]);
                xss.pop();
                i--;
                j--;
            }else if (sub_result != sig_Error){
                // fprintf(stderr, "BWD-SUB-RES (i = %d, j = %d)\n", i, j);
                // fprintf(stderr, " >>> (i) "); printSigs(xss[i]); fprintf(stderr, "\n");
                // fprintf(stderr, " >>> (j) "); printSigs(xss[j]); fprintf(stderr, "\n");
                xss[j].moveTo(tmp);
                xss[i-1].moveTo(xss[j]);
                xss[i].moveTo(xss[i-1]);
                xss.last().moveTo(xss[i]);
                tmp.moveTo(xss.last());
                i--;
                remove(xss.last(), sub_result);
            }
        }
    next_i:
        // fprintf(stderr, "NEXT (i = %d, xss.length = %d)\n", i, xss.size());
        ;
    }
}

static inline bool implies(const vec<vec<Sig> >& cnf, const vec<Sig>& clause)
{
    vec<vec<Sig> > tmp;

    // Add unit clauses negating the single input clause:
    //
    for (int i = 0; i < clause.size(); i++){
        tmp.push();
        tmp.last().push(~clause[i]);
    }

    // Copy the input cnf:
    //
    for (int i = 0; i < cnf.size(); i++){
        tmp.push();
        cnf[i].copyTo(tmp.last());
    }

    // Normalize (at least as strong as unit propagation):
    //
    subsumptionResolutionSaturation(tmp);
    if (tmp.size() == 0){
        fprintf(stderr, " >>> WEIRD RESULT FROM IMPLIES CHECK:\n");
        fprintf(stderr, " === ");
        printSigs(clause);
        fprintf(stderr, "\n");

        for (int i = 0; i < cnf.size(); i++){
            fprintf(stderr, " --- ");
            printSigs(cnf[i]);
            fprintf(stderr, "\n");
        } }

    assert(tmp.size() > 0);

    // Check for the case were the result is a single empty clause:
    //
    return tmp.size() == 1 && tmp[0].size() == 0;
}

#if 0
// What were this intended for?
static inline bool resolve(const vec<Sig>& xs, const vec<Sig>& ys, vec<Sig>& zs)
{
    Sig pivot = sig_Undef;

    for (int i = 0; i < xs.size(); i++)
        for (int j = 0; j < ys.size(); j++)
            if (xs[i] == ~ys[j])
                if (pivot == sig_Undef)
                    pivot = xs[i];
                else
                    return false;

    zs.clear();
    for (int i = 0; i < xs.size(); i++)
        if (xs[i] != pivot)
            zs.push(xs[i]);

    for (int i = 0; i < ys.size(); i++)
        if (ys[i] != ~pivot)
            zs.push(ys[i]);

    return true;
}

static inline void removeRedundant(vec<vec<Sig> >& xss)
{
    vec<vec<Sig> > tmp;
    for (int i = 0; i < xss.size(); i++){
        tmp.clear();
        for (int j = 0; j < xss.size(); j++)
            if (i != j){
                tmp.push();
                xss[j].copyTo(tmp.last());
            }

        if (implies(tmp, xss[i])){
            xss.last().moveTo(xss[i]);
            xss.pop();
            i--;
        }
    }
}
#endif

void Minisat::normalizeTwoLevel(vec<vec<Sig> >& xss, const vec<vec<Sig> >& context)
{
    // Basic normalization:
    //
    for (int i = 0; i < xss.size(); i++)
        normalizeOrs(xss[i]);

    for (int i = 0; i < xss.size(); i++)
        if (xss[i].size() == 0){
            xss.clear();
            xss.push();
        }else if (xss[i].size() == 1 && xss[i][0] == sig_True){
            xss.last().moveTo(xss[i]);
            xss.pop();
            i--; }

    #if 0
    int before_size = 0;
    vec<vec<Sig> > copy;
    for (int i = 0; i < xss.size(); i++){
        copy.push();
        xss[i].copyTo(copy.last());
        before_size += copy.last().size();
    }
    #endif

    // if (xss.size() > 15)
    //     fprintf(stderr, "cnf-size: %d .... \n", xss.size());
    // Elaborate normalization:
    //
    if (xss.size() < 17)
        subsumptionResolutionSaturation(xss, context);

    bool check = false;
    for (int i = 0; i < xss.size(); i++)
        check |= xss[i].size() == 0;
    assert(!check || xss.size() == 1);

    #if 0

    int after_size = 0;
    for (int i = 0; i < xss.size(); i++)
        after_size += xss[i].size();

    if (after_size < before_size){
        fprintf(stderr, " >>> SUCCESSFUL REDUNDANCY REMOVAL:\n");
        fprintf(stderr, " --- BEFORE:\n");
        for (int i = 0; i < copy.size(); i++){
            fprintf(stderr, " --- ");
            printSigs(copy[i]);
            fprintf(stderr, "\n");
        }
        fprintf(stderr, " --- AFTER:\n");
        for (int i = 0; i < xss.size(); i++){
            fprintf(stderr, " --- ");
            printSigs(xss[i]);
            fprintf(stderr, "\n");
        }
    }
    #endif

    // Remove remaining clauses that are implied by the others:
    //
#if 0

    if (xss.size() > 1 && xss.size() < 17)
        removeRedundant(xss);

#endif
}
<commit_msg>Wibbles: Activate some ifdefs.<commit_after>/*********************************************************************************[Normalization.C]
Copyright (c) 2008, Niklas Sorensson

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************************************/

#include "mtl/Sort.h"
#include "mtl/Alg.h"
#include "circ/Normalization.h"

using namespace Minisat;

//=================================================================================================
// Normalization functions for different n-ary gate types:

void Minisat::normalizeXors(vec<Sig>& xs)
{
    // Calculate the parity and make inputs unsigned:
    //
    bool pol = false;
    for (int i = 0; i < xs.size(); i++){
        pol   = pol ^ sign(xs[i]);
        xs[i] = mkSig(gate(xs[i]));
    }

    // Sort and remove duplicates properly:
    //
    int  i, j, k;
    sort(xs);
    for (i = j = 0; i < xs.size(); i = k){
        // Check how many times xs[i] is repeated:
        for (k = i; k < xs.size() && xs[k] == xs[i]; k++)
            ;

        // fprintf(stderr, "i = %d, j = %d, k = %d, k - i = %d\n", i, j, k, k - i);

        // Only if xs[i] occurs an odd number of times it should be kept:
        if ((k - i) % 2 == 1)
            xs[j++] = xs[i];
    }
    xs.shrink(i - j);

    // Remove possible remaining constant (can only be one, and it must occur first):
    if (xs.size() > 0 && xs[0] == sig_True){
        for (i = 1; i < xs.size(); i++)
            xs[i-1] = xs[i];
        xs.shrink(1);
        pol = !pol;
    }

    if (xs.size() > 0)
        // Attach the sign to the last element:
        xs.last() = xs.last() ^ pol;
    else if (pol)
        // If the xor-chain is empty but the output is expected to be negated, add a constant true:
        xs.push(sig_True);
}

void Minisat::normalizeAnds(vec<Sig>& xs)
{
    int  i, j;
    sort(xs);

    // Remove duplicates and detect inconsistencies:
    for (i = j = 1; i < xs.size(); i++)
        if (xs[i] == ~xs[j-1]){
            xs.clear();
            xs.push(sig_False);
            return;
        }else if (xs[i] != xs[j-1])
            xs[j++] = xs[i];

    xs.shrink(i - j);

    // Remove constant true:
    if (xs.size() > 0 && xs[0] == sig_True){
        for (i = 1; i < xs.size(); i++)
            xs[i-1] = xs[i];
        xs.shrink(1);
    }

    // Detect constant false:
    if (xs.size() > 0 && xs[0] == sig_False){
        xs.clear();
        xs.push(sig_False);
    }
}

void Minisat::normalizeOrs(vec<Sig>& xs)
{
    int  i, j;
    sort(xs);

    // Remove duplicates and detect tautologies:
    for (i = j = 1; i < xs.size(); i++)
        if (xs[i] == ~xs[j-1]){
            xs.clear();
            xs.push(sig_True);
            return;
        }else if (xs[i] != xs[j-1])
            xs[j++] = xs[i];

    xs.shrink(i - j);

    // Detect constant true:
    if (xs.size() > 0 && xs[0] == sig_True){
        xs.clear();
        xs.push(sig_True);
    }

    // Remove constant false:
    if (xs.size() > 0 && xs[0] == sig_False){
        for (i = 1; i < xs.size(); i++)
            xs[i-1] = xs[i];
        xs.shrink(1);
    }
}

// Shamelessly stolen from "SolverTypes.h" ...
static inline Sig subsumes(const vec<Sig>& xs, const vec<Sig>& ys)
{
    if (ys.size() < xs.size())
        return sig_Error;

    Sig ret = sig_Undef;
    for (int i = 0; i < xs.size(); i++){
        // search for xs[i] or ~xs[i]
        for (int j = 0; j < ys.size(); j++)
            if (xs[i] == ys[j])
                goto ok;
            else if (ret == sig_Undef && xs[i] == ~ys[j]){
                ret = ys[j];
                goto ok;
            }

        // did not find it
        return sig_Error;
    ok:;
    }

    return ret;
}

static void printSigs(const vec<Sig>& xs)
{
    fprintf(stderr, "{ ");
    for (int i = 0; i < xs.size(); i++)
        fprintf(stderr, "%s%s%d ", sign(xs[i])?"-":"", type(xs[i]) == gtype_Inp ? "$" : "@", index(gate(xs[i])));
    fprintf(stderr, "}");
}

const vec<vec<Sig> > Minisat::empty_context;

static void subsumptionResolutionSaturation(vec<vec<Sig> >& xss, const vec<vec<Sig> >& context = empty_context)
{
    // fprintf(stderr, "STARTING SUBSUMPTION RESULTION:\n");
    // for (int i = 0; i < xss.size(); i++){
    //     fprintf(stderr, " --- ");
    //     printSigs(xss[i]);
    //     fprintf(stderr, "\n");
    // }
    vec<Sig> tmp;

    // INVARIANT: xs[0] .. xs[i] is normalized.
    //
    for (int i = 0; i < xss.size(); i++){
        // fprintf(stderr, "PROCESSING (i = %d, xss.length = %d)\n", i, xss.size());

        // Check contextual forwards subsumption:
        for (int j = 0; j < context.size(); j++){
            Sig sub_result = subsumes(context[j], xss[i]);

            if (sub_result == sig_Undef){
                // fprintf(stderr, "FWD-CTX-SUB (i = %d, j = %d)\n", i, j);
                // fprintf(stderr, " >>> (i) "); printSigs(xss[i]); fprintf(stderr, "\n");
                // fprintf(stderr, " >>> (j) "); printSigs(context[j]); fprintf(stderr, "\n");
                xss.last().moveTo(xss[i]);
                xss.pop();
                i--;
                goto next_i;
            }else if (sub_result != sig_Error){
                // fprintf(stderr, "FWD-CTX-SUB-RES (i = %d, j = %d)\n", i, j);
                // fprintf(stderr, " >>> (i) "); printSigs(xss[i]); fprintf(stderr, "\n");
                // fprintf(stderr, " >>> (j) "); printSigs(context[j]); fprintf(stderr, "\n");
                remove(xss[i], sub_result);
            }
        }

        // Check forwards subsumption:
        for (int j = 0; j < i; j++){
            Sig sub_result = subsumes(xss[j], xss[i]);

            if (sub_result == sig_Undef){
                // fprintf(stderr, "FWD-SUB (i = %d, j = %d)\n", i, j);
                // fprintf(stderr, " >>> (i) "); printSigs(xss[i]); fprintf(stderr, "\n");
                // fprintf(stderr, " >>> (j) "); printSigs(xss[j]); fprintf(stderr, "\n");
                xss.last().moveTo(xss[i]);
                xss.pop();
                i--;
                goto next_i;
            }else if (sub_result != sig_Error){
                // fprintf(stderr, "FWD-SUB-RES (i = %d, j = %d)\n", i, j);
                // fprintf(stderr, " >>> (i) "); printSigs(xss[i]); fprintf(stderr, "\n");
                // fprintf(stderr, " >>> (j) "); printSigs(xss[j]); fprintf(stderr, "\n");
                remove(xss[i], sub_result);
            }
        }

        // Check backwards subsumption:
        for (int j = 0; j < i; j++){
            Sig sub_result = subsumes(xss[i], xss[j]);

            if (sub_result == sig_Undef){
                // fprintf(stderr, "BWD-SUB (i = %d, j = %d)\n", i, j);
                // fprintf(stderr, " >>> (i) "); printSigs(xss[i]); fprintf(stderr, "\n");
                // fprintf(stderr, " >>> (j) "); printSigs(xss[j]); fprintf(stderr, "\n");
                xss[i-1].moveTo(xss[j]);
                xss[i].moveTo(xss[i-1]);
                xss.last().moveTo(xss[i]);
                xss.pop();
                i--;
                j--;
            }else if (sub_result != sig_Error){
                // fprintf(stderr, "BWD-SUB-RES (i = %d, j = %d)\n", i, j);
                // fprintf(stderr, " >>> (i) "); printSigs(xss[i]); fprintf(stderr, "\n");
                // fprintf(stderr, " >>> (j) "); printSigs(xss[j]); fprintf(stderr, "\n");
                xss[j].moveTo(tmp);
                xss[i-1].moveTo(xss[j]);
                xss[i].moveTo(xss[i-1]);
                xss.last().moveTo(xss[i]);
                tmp.moveTo(xss.last());
                i--;
                remove(xss.last(), sub_result);
            }
        }
    next_i:
        // fprintf(stderr, "NEXT (i = %d, xss.length = %d)\n", i, xss.size());
        ;
    }
}

static inline bool implies(const vec<vec<Sig> >& cnf, const vec<Sig>& clause)
{
    vec<vec<Sig> > tmp;

    // Add unit clauses negating the single input clause:
    //
    for (int i = 0; i < clause.size(); i++){
        tmp.push();
        tmp.last().push(~clause[i]);
    }

    // Copy the input cnf:
    //
    for (int i = 0; i < cnf.size(); i++){
        tmp.push();
        cnf[i].copyTo(tmp.last());
    }

    // Normalize (at least as strong as unit propagation):
    //
    subsumptionResolutionSaturation(tmp);
    if (tmp.size() == 0){
        fprintf(stderr, " >>> WEIRD RESULT FROM IMPLIES CHECK:\n");
        fprintf(stderr, " === ");
        printSigs(clause);
        fprintf(stderr, "\n");

        for (int i = 0; i < cnf.size(); i++){
            fprintf(stderr, " --- ");
            printSigs(cnf[i]);
            fprintf(stderr, "\n");
        } }

    assert(tmp.size() > 0);

    // Check for the case were the result is a single empty clause:
    //
    return tmp.size() == 1 && tmp[0].size() == 0;
}

#if 1
// What were this intended for?
static inline bool resolve(const vec<Sig>& xs, const vec<Sig>& ys, vec<Sig>& zs)
{
    Sig pivot = sig_Undef;

    for (int i = 0; i < xs.size(); i++)
        for (int j = 0; j < ys.size(); j++)
            if (xs[i] == ~ys[j])
                if (pivot == sig_Undef)
                    pivot = xs[i];
                else
                    return false;

    zs.clear();
    for (int i = 0; i < xs.size(); i++)
        if (xs[i] != pivot)
            zs.push(xs[i]);

    for (int i = 0; i < ys.size(); i++)
        if (ys[i] != ~pivot)
            zs.push(ys[i]);

    return true;
}

static inline void removeRedundant(vec<vec<Sig> >& xss)
{
    vec<vec<Sig> > tmp;
    for (int i = 0; i < xss.size(); i++){
        tmp.clear();
        for (int j = 0; j < xss.size(); j++)
            if (i != j){
                tmp.push();
                xss[j].copyTo(tmp.last());
            }

        if (implies(tmp, xss[i])){
            xss.last().moveTo(xss[i]);
            xss.pop();
            i--;
        }
    }
}
#endif

void Minisat::normalizeTwoLevel(vec<vec<Sig> >& xss, const vec<vec<Sig> >& context)
{
    // Basic normalization:
    //
    for (int i = 0; i < xss.size(); i++)
        normalizeOrs(xss[i]);

    for (int i = 0; i < xss.size(); i++)
        if (xss[i].size() == 0){
            xss.clear();
            xss.push();
        }else if (xss[i].size() == 1 && xss[i][0] == sig_True){
            xss.last().moveTo(xss[i]);
            xss.pop();
            i--; }

    #if 0
    int before_size = 0;
    vec<vec<Sig> > copy;
    for (int i = 0; i < xss.size(); i++){
        copy.push();
        xss[i].copyTo(copy.last());
        before_size += copy.last().size();
    }
    #endif

    // if (xss.size() > 15)
    //     fprintf(stderr, "cnf-size: %d .... \n", xss.size());
    // Elaborate normalization:
    //
    if (xss.size() < 17)
        subsumptionResolutionSaturation(xss, context);

    bool check = false;
    for (int i = 0; i < xss.size(); i++)
        check |= xss[i].size() == 0;
    assert(!check || xss.size() == 1);

    #if 0

    int after_size = 0;
    for (int i = 0; i < xss.size(); i++)
        after_size += xss[i].size();

    if (after_size < before_size){
        fprintf(stderr, " >>> SUCCESSFUL REDUNDANCY REMOVAL:\n");
        fprintf(stderr, " --- BEFORE:\n");
        for (int i = 0; i < copy.size(); i++){
            fprintf(stderr, " --- ");
            printSigs(copy[i]);
            fprintf(stderr, "\n");
        }
        fprintf(stderr, " --- AFTER:\n");
        for (int i = 0; i < xss.size(); i++){
            fprintf(stderr, " --- ");
            printSigs(xss[i]);
            fprintf(stderr, "\n");
        }
    }
    #endif

    // Remove remaining clauses that are implied by the others:
    //
#if 1

    if (xss.size() > 1 && xss.size() < 17)
        removeRedundant(xss);

#endif
}
<|endoftext|>


<commit_before>#include "SAVEGAME.H"

#include "CONTROL.H"
#include "GAMEFLOW.H"
#include "SPECIFIC.H"

#include <string>

char FromTitle;
char JustLoaded;
char* MGSaveGamePtr;
static int SGcount;
static char* SGpoint;
struct savegame_info savegame;

void sgRestoreGame()//55B88, 55FEC (F)
{
	SGcount = 0;
	SGpoint = &MGSaveGamePtr[sizeof(savegame_info)];

	GameTimer = savegame.Game.Timer;
	gfCurrentLevel = savegame.CurrentLevel;

	RestoreLevelData(1);
	RestoreLaraData(1);
}

void sgSaveGame()//55AF8(<), 55F5C(<)
{

	SGpoint = &MGSaveGamePtr[436];
	SGcount = 0;
	savegame.CurrentLevel = gfCurrentLevel;
	SaveLevelData(1);
	savegame.Game.Timer = GameTimer;
	SaveLaraData();

	MGSaveGamePtr[7678] = GetRandomControl();
	memcpy(&MGSaveGamePtr, &savegame, sizeof(savegame_info));
	savegame.Checksum = GameTimer;

	return;
}

void RestoreLevelData(int FullSave)//54B08, 54F6C
{
	S_Warn("[RestoreLevelData] - Unimplemented!\n");
}

void SaveLevelData(int FullSave)//53AAC, 53F10
{
	S_Warn("[SaveLevelData] - Unimplemented!\n");
}

void RestoreLaraData(int FullSave)//538D0, 53D34
{
	S_Warn("[RestoreLaraData] - Unimplemented!\n");
}

void SaveLaraData()//53738, 53B9C
{
	S_Warn("[SaveLaraData] - Unimplemented!\n");
}

int CheckSumValid(char* buffer)//53720, 53B84
{
	return (*(short*) buffer[0]) ^ (*(short*) buffer[7678]) < 1 ? 1 : 0;
}

void ReadSG(char* pointer, int size)//536E0, 53B44 (F)
{
	SGcount += size;

	if (size > 0)
	{
		while (size-- > 0)
		{
			*pointer++ = *SGpoint++;
		}
	}

	return;
}

void WriteSG(char* pointer, int size)//536A0, 53B04
{
	SGcount += size;

	if (size > 0)
	{
		while (size-- > 0)
		{
			*SGpoint++ = *pointer++;
		}
	}
	S_Warn("[WriteSG] - Unimplemented!\n");
}

<commit_msg>Attempt to resolve linux build failure.<commit_after>#include "SAVEGAME.H"

#include "CONTROL.H"
#include "GAMEFLOW.H"
#include "SPECIFIC.H"

#include <string.h>

char FromTitle;
char JustLoaded;
char* MGSaveGamePtr;
static int SGcount;
static char* SGpoint;
struct savegame_info savegame;

void sgRestoreGame()//55B88, 55FEC (F)
{
	SGcount = 0;
	SGpoint = &MGSaveGamePtr[sizeof(savegame_info)];

	GameTimer = savegame.Game.Timer;
	gfCurrentLevel = savegame.CurrentLevel;

	RestoreLevelData(1);
	RestoreLaraData(1);
}

void sgSaveGame()//55AF8(<), 55F5C(<)
{

	SGpoint = &MGSaveGamePtr[sizeof(savegame_info)];
	SGcount = 0;
	savegame.CurrentLevel = gfCurrentLevel;
	SaveLevelData(1);
	savegame.Game.Timer = GameTimer;
	SaveLaraData();

	MGSaveGamePtr[7678] = GetRandomControl();
	memcpy(&MGSaveGamePtr, &savegame, sizeof(savegame_info));
	savegame.Checksum = GameTimer;

	return;
}

void RestoreLevelData(int FullSave)//54B08, 54F6C
{
	S_Warn("[RestoreLevelData] - Unimplemented!\n");
}

void SaveLevelData(int FullSave)//53AAC, 53F10
{
	S_Warn("[SaveLevelData] - Unimplemented!\n");
}

void RestoreLaraData(int FullSave)//538D0, 53D34
{
	S_Warn("[RestoreLaraData] - Unimplemented!\n");
}

void SaveLaraData()//53738, 53B9C
{
	S_Warn("[SaveLaraData] - Unimplemented!\n");
}

int CheckSumValid(char* buffer)//53720, 53B84
{
	return (*(short*) buffer[0]) ^ (*(short*) buffer[7678]) < 1 ? 1 : 0;
}

void ReadSG(char* pointer, int size)//536E0, 53B44 (F)
{
	SGcount += size;

	if (size > 0)
	{
		while (size-- > 0)
		{
			*pointer++ = *SGpoint++;
		}
	}

	return;
}

void WriteSG(char* pointer, int size)//536A0, 53B04
{
	SGcount += size;

	if (size > 0)
	{
		while (size-- > 0)
		{
			*SGpoint++ = *pointer++;
		}
	}
}

<|endoftext|>


<commit_before>#include "GameProcess.h"
#include "Object.h"
#include "Engine.h"
#include "World.h"
#include "App.h"
#include "ToolsCamera.h"
#include "ControlsApp.h"
#include "MathLib.h"
#include "Game.h"
#include "Editor.h"

using namespace MathLib;

CGameProcess::CGameProcess(void)
{

}

CGameProcess::~CGameProcess(void)
{

}
int CGameProcess::Init()
{
	g_Engine.pFileSystem->CacheFilesFormExt("char");
	g_Engine.pFileSystem->CacheFilesFormExt("node");
	g_Engine.pFileSystem->CacheFilesFormExt("smesh");
	g_Engine.pFileSystem->CacheFilesFormExt("sanim");

	g_Engine.pWorld->LoadWorld("data/scene/terrain/test/test.world");
	//g_Engine.pWorld->LoadWorld("data/scene/terrain/cj/cj.world");
	g_Engine.pControls->SetKeyPressFunc(KeyPress);
	g_Engine.pControls->SetKeyReleaseFunc(KeyRelease);

	m_pRole = new CFPSRoleLocal();
	m_pRole->Init(10001, "data/role/hero/FpsRole/fps.char");		//ؽɫԴ

	m_pRole->SetActorPosition(vec3(0, 0, 0));	//ýɫʼλáŴΪԭ㣬άϵvec3
	m_pSkillSystem = new CSkillSystem(this);
	m_pCameraBase = new CCameraBase();
	m_pCameraBase->SetEnabled(1);
	g_pSysControl->SetMouseGrab(1);

	m_pStarControl = new CStarControl();
	m_pRayControl = new CRayControl();

	return 1;
}

int CGameProcess::ShutDown()			//رϷ
{
	delete m_pRole;
	delete m_pSkillSystem;
	delete m_pCameraBase;
	delete m_pStarControl;
	delete m_pRayControl;

	DelAllListen();
	return 0;
}

int CGameProcess::Update()
{

	return 0;
}
<commit_msg>Signed-off-by: mrlitong <litongtongxue@gmail.com><commit_after>#include "GameProcess.h"
#include "Object.h"
#include "Engine.h"
#include "World.h"
#include "App.h"
#include "ToolsCamera.h"
#include "ControlsApp.h"
#include "MathLib.h"
#include "Game.h"
#include "Editor.h"

using namespace MathLib;

CGameProcess::CGameProcess(void)
{

}

CGameProcess::~CGameProcess(void)
{

}
int CGameProcess::Init()
{
	g_Engine.pFileSystem->CacheFilesFormExt("char");
	g_Engine.pFileSystem->CacheFilesFormExt("node");
	g_Engine.pFileSystem->CacheFilesFormExt("smesh");
	g_Engine.pFileSystem->CacheFilesFormExt("sanim");

	g_Engine.pWorld->LoadWorld("data/scene/terrain/test/test.world");
	//g_Engine.pWorld->LoadWorld("data/scene/terrain/cj/cj.world");
	g_Engine.pControls->SetKeyPressFunc(KeyPress);
	g_Engine.pControls->SetKeyReleaseFunc(KeyRelease);

	m_pRole = new CFPSRoleLocal();
	m_pRole->Init(10001, "data/role/hero/FpsRole/fps.char");		//ؽɫԴ

	m_pRole->SetActorPosition(vec3(0, 0, 0));	//ýɫʼλáŴΪԭ㣬άϵvec3
	m_pSkillSystem = new CSkillSystem(this);
	m_pCameraBase = new CCameraBase();
	m_pCameraBase->SetEnabled(1);
	g_pSysControl->SetMouseGrab(1);

	m_pStarControl = new CStarControl();
	m_pRayControl = new CRayControl();

	return 1;
}

int CGameProcess::ShutDown()			//رϷ
{
	delete m_pRole;
	delete m_pSkillSystem;
	delete m_pCameraBase;
	delete m_pStarControl;
	delete m_pRayControl;

	DelAllListen();
	return 0;
}

int CGameProcess::Update()
{
	float ifps = g_Engine.pGame->GetIFps();

	return 0;
}
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "controller.h"
#include "internal/query_parser.h"
#include "internal/parse_tree.h"
#include "internal/date_time_parser.h"

namespace You {
namespace NLP {

using Internal::QueryParser;
using Internal::DateTimeParser;
using Internal::QUERY;
using Internal::ADD_QUERY;
using Date = boost::gregorian::date;

namespace {

/// The query builder that will send the query to the appropriate builder
/// in the controller class.
class QueryBuilderVisitor : public boost::static_visitor<
	std::shared_ptr<QueryEngine::Query>> {
public:
	/// Visitor implementation.
	///
	/// \param[in] query The actual query from the parse tree.
	template<typename QueryType>
	std::shared_ptr<QueryEngine::Query> operator()(const QueryType& query) const {
		return build(query);
	}

private:
	/// Builds a query engine query from the given syntax tree.
	///
	/// \param[in] query The syntax tree to build a query from.
	static std::shared_ptr<QueryEngine::Query> build(const ADD_QUERY& query);

	/// Converts a boost::gregorian::date to a time_t.
	///
	/// \param[in] date The date to convert.
	static time_t dateToTimeT(const Date& date);
};

}  // namespace

Result Controller::query(
	const std::wstring& query,
	const TaskList& context) const {
	QUERY parseTree = QueryParser::parse(query);

	QueryBuilderVisitor visitor;
	std::shared_ptr<QueryEngine::Query> queryRef =
		boost::apply_visitor(visitor, parseTree);

	QueryEngine::Response response = QueryEngine::executeQuery(queryRef);
	return Result(response);
}

std::shared_ptr<QueryEngine::Query>
QueryBuilderVisitor::build(const ADD_QUERY& query) {
	std::wstring& description = query.description;
	boost::gregorian::date deadline = DateTimeParser::parse(query.due);

	return QueryEngine::AddTask(
		query.description,
		dateToTimeT(deadline),
		Task::Priority::NORMAL,
		Task::Dependencies());
}
}  // namespace NLP
}  // namespace You
<commit_msg>Fix compile error.<commit_after>#include "stdafx.h"
#include "controller.h"
#include "internal/query_parser.h"
#include "internal/parse_tree.h"
#include "internal/date_time_parser.h"

namespace You {
namespace NLP {

using Internal::QueryParser;
using Internal::DateTimeParser;
using Internal::QUERY;
using Internal::ADD_QUERY;
using Date = boost::gregorian::date;

namespace {

/// The query builder that will send the query to the appropriate builder
/// in the controller class.
class QueryBuilderVisitor : public boost::static_visitor<
	std::shared_ptr<QueryEngine::Query>> {
public:
	/// Visitor implementation.
	///
	/// \param[in] query The actual query from the parse tree.
	template<typename QueryType>
	std::shared_ptr<QueryEngine::Query> operator()(const QueryType& query) const {
		return build(query);
	}

private:
	/// Builds a query engine query from the given syntax tree.
	///
	/// \param[in] query The syntax tree to build a query from.
	static std::shared_ptr<QueryEngine::Query> build(const ADD_QUERY& query);

	/// Converts a boost::gregorian::date to a time_t.
	///
	/// \param[in] date The date to convert.
	static time_t dateToTimeT(const Date& date);
};

}  // namespace

Result Controller::query(
	const std::wstring& query,
	const TaskList& context) const {
	QUERY parseTree = QueryParser::parse(query);

	QueryBuilderVisitor visitor;
	std::shared_ptr<QueryEngine::Query> queryRef =
		boost::apply_visitor(visitor, parseTree);

	QueryEngine::Response response = QueryEngine::executeQuery(queryRef);
	return Result(response);
}

std::shared_ptr<QueryEngine::Query>
QueryBuilderVisitor::build(const ADD_QUERY& query) {
	const std::wstring& description = query.description;
	boost::gregorian::date deadline = DateTimeParser::parse(query.due);

	return QueryEngine::AddTask(
		query.description,
		dateToTimeT(deadline),
		Task::Priority::NORMAL,
		Task::Dependencies());
}
}  // namespace NLP
}  // namespace You
<|endoftext|>


<commit_before>// Copyright 2014-2015 Project Vogue. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "elang/hir/type_factory.h"

#include <unordered_map>
#include <utility>

#include "base/logging.h"
#include "elang/base/zone.h"
#include "elang/hir/factory_config.h"
#include "elang/hir/types.h"

namespace elang {
namespace hir {
typedef std::pair<Type*, Type*> TypePair;
}  // namespace hir
}  // namespace elang

namespace std {
using elang::hir::Type;
using elang::hir::TypePair;

template <>
struct hash<TypePair> {
  size_t operator()(const TypePair& pair) const {
    return std::hash<Type*>()(pair.first) ^ std::hash<Type*>()(pair.second);
  }
};
}  // namespace std

namespace elang {
namespace hir {

//////////////////////////////////////////////////////////////////////
//
// TypeFactory::FunctionTypeFactory
//
class TypeFactory::FunctionTypeFactory final {
 public:
  explicit FunctionTypeFactory(Zone* zone) : zone_(zone) {}
  ~FunctionTypeFactory() = default;

  FunctionType* NewFunctionType(Type* return_type, Type* parameters_type);

 private:
  std::unordered_map<TypePair, FunctionType*> map_;
  Zone* const zone_;

  DISALLOW_COPY_AND_ASSIGN(FunctionTypeFactory);
};

FunctionType* TypeFactory::FunctionTypeFactory::NewFunctionType(
    Type* return_type,
    Type* parameters_type) {
  const auto key = std::make_pair(return_type, parameters_type);
  const auto it = map_.find(key);
  if (it != map_.end())
    return it->second;
  auto const new_type =
      new (zone_) FunctionType(zone_, return_type, parameters_type);
  map_[key] = new_type;
  return new_type;
}

//////////////////////////////////////////////////////////////////////
//
// TypeFactory
//
TypeFactory::TypeFactory(const FactoryConfig& config)
    :
#define V(Name, name, ...) name##_type_(new (zone()) Name##Type(zone())),
      FOR_EACH_HIR_PRIMITIVE_TYPE(V)
#undef V
          function_type_factory_(new FunctionTypeFactory(zone())),
      string_type_(new (zone()) StringType(zone(), config.string_type_name)) {
}

TypeFactory::~TypeFactory() {
}

#define V(Name, name, ...) \
  Name##Type* TypeFactory::name##_type() const { return name##_type_; }
FOR_EACH_HIR_PRIMITIVE_TYPE(V)
#undef V

ExternalType* TypeFactory::NewExternalType(AtomicString* name) {
  return new (zone()) ExternalType(zone(), name);
}

FunctionType* TypeFactory::NewFunctionType(Type* return_type,
                                           Type* parameters_type) {
  return function_type_factory_->NewFunctionType(return_type, parameters_type);
}

PointerType* TypeFactory::NewPointerType(Type* pointee) {
  auto it = pointer_type_map_.find(pointee);
  if (it != pointer_type_map_.end())
    return it->second;
  auto const new_pointer_type = new (zone()) PointerType(zone(), pointee);
  pointer_type_map_[pointee] = new_pointer_type;
  return new_pointer_type;
}

TupleType* TypeFactory::NewTupleType(const std::vector<Type*>& members) {
  DCHECK(!members.empty());
#if _DEBUG
  for (auto const member : members) {
    DCHECK(!member->is<VoidType>());
  }
#endif
  return new (zone()) TupleType(zone(), members);
}

}  // namespace hir
}  // namespace elang
<commit_msg>elang/hir: Make |TypeFactory::NewTupleType()| not to accept single member.<commit_after>// Copyright 2014-2015 Project Vogue. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "elang/hir/type_factory.h"

#include <unordered_map>
#include <utility>

#include "base/logging.h"
#include "elang/base/zone.h"
#include "elang/hir/factory_config.h"
#include "elang/hir/types.h"

namespace elang {
namespace hir {
typedef std::pair<Type*, Type*> TypePair;
}  // namespace hir
}  // namespace elang

namespace std {
using elang::hir::Type;
using elang::hir::TypePair;

template <>
struct hash<TypePair> {
  size_t operator()(const TypePair& pair) const {
    return std::hash<Type*>()(pair.first) ^ std::hash<Type*>()(pair.second);
  }
};
}  // namespace std

namespace elang {
namespace hir {

//////////////////////////////////////////////////////////////////////
//
// TypeFactory::FunctionTypeFactory
//
class TypeFactory::FunctionTypeFactory final {
 public:
  explicit FunctionTypeFactory(Zone* zone) : zone_(zone) {}
  ~FunctionTypeFactory() = default;

  FunctionType* NewFunctionType(Type* return_type, Type* parameters_type);

 private:
  std::unordered_map<TypePair, FunctionType*> map_;
  Zone* const zone_;

  DISALLOW_COPY_AND_ASSIGN(FunctionTypeFactory);
};

FunctionType* TypeFactory::FunctionTypeFactory::NewFunctionType(
    Type* return_type,
    Type* parameters_type) {
  const auto key = std::make_pair(return_type, parameters_type);
  const auto it = map_.find(key);
  if (it != map_.end())
    return it->second;
  auto const new_type =
      new (zone_) FunctionType(zone_, return_type, parameters_type);
  map_[key] = new_type;
  return new_type;
}

//////////////////////////////////////////////////////////////////////
//
// TypeFactory
//
TypeFactory::TypeFactory(const FactoryConfig& config)
    :
#define V(Name, name, ...) name##_type_(new (zone()) Name##Type(zone())),
      FOR_EACH_HIR_PRIMITIVE_TYPE(V)
#undef V
          function_type_factory_(new FunctionTypeFactory(zone())),
      string_type_(new (zone()) StringType(zone(), config.string_type_name)) {
}

TypeFactory::~TypeFactory() {
}

#define V(Name, name, ...) \
  Name##Type* TypeFactory::name##_type() const { return name##_type_; }
FOR_EACH_HIR_PRIMITIVE_TYPE(V)
#undef V

ExternalType* TypeFactory::NewExternalType(AtomicString* name) {
  return new (zone()) ExternalType(zone(), name);
}

FunctionType* TypeFactory::NewFunctionType(Type* return_type,
                                           Type* parameters_type) {
  return function_type_factory_->NewFunctionType(return_type, parameters_type);
}

PointerType* TypeFactory::NewPointerType(Type* pointee) {
  auto it = pointer_type_map_.find(pointee);
  if (it != pointer_type_map_.end())
    return it->second;
  auto const new_pointer_type = new (zone()) PointerType(zone(), pointee);
  pointer_type_map_[pointee] = new_pointer_type;
  return new_pointer_type;
}

TupleType* TypeFactory::NewTupleType(const std::vector<Type*>& members) {
  DCHECK_GE(members.size(), 2u);
#if _DEBUG
  for (auto const member : members) {
    DCHECK(!member->is<VoidType>());
  }
#endif
  return new (zone()) TupleType(zone(), members);
}

}  // namespace hir
}  // namespace elang
<|endoftext|>


<commit_before>/*
 * Copyright 2015 - 2018 gtalent2@gmail.com
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#if defined(OX_USE_STDLIB)
#include <iomanip>
#include <iostream>
#endif

#include <ox/mc/write.hpp>

#include "trace.hpp"

namespace ox::trace {

OutStream::OutStream(const char *file, int line, const char *ch, const char *msg) {
	m_msg.file = file;
	m_msg.line = line;
	m_msg.ch = ch;
	m_msg.msg = msg;
}

OutStream::~OutStream() {
	constexpr std::size_t buffLen = 1024;
	std::size_t size = 0;
	uint8_t buff[buffLen];
	writeMC(buff, buffLen, &m_msg, &size);
}

StdOutStream::StdOutStream(const char *file, int line, const char *ch, const char *msg) {
	m_msg.file = file;
	m_msg.line = line;
	m_msg.ch = ch;
	m_msg.msg = msg;
}

StdOutStream::~StdOutStream() {
#if defined(OX_USE_STDLIB)
	std::cout << std::setw(53) << std::left << m_msg.ch.c_str() << '|';
	std::cout << std::setw(65) << std::left << m_msg.msg.c_str() << '|';
	std::cout << " " << m_msg.file.c_str() << ':' << m_msg.line << "\n";
#endif
}

void logError(const char *file, int line, Error err) {
	if (err) {
		ErrorInfo ei(err);
		TraceStream trc(file, line, "ox::error");
		trc <<  "Error:" << ei.errCode;
		if (ei.file != nullptr) {
			trc << "(" << reinterpret_cast<const char*>(ei.file) << ":" << ei.line << ")";
		}
	}
}

}
<commit_msg>[ox/trace] Add environment variable to enable logging<commit_after>/*
 * Copyright 2015 - 2018 gtalent2@gmail.com
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#if defined(OX_USE_STDLIB)
#include <iomanip>
#include <iostream>
#endif

#include <ox/mc/write.hpp>

#include "trace.hpp"

namespace ox::trace {

static const auto OxPrintTrace = std::getenv("OXTRACE") != nullptr;

OutStream::OutStream(const char *file, int line, const char *ch, const char *msg) {
	m_msg.file = file;
	m_msg.line = line;
	m_msg.ch = ch;
	m_msg.msg = msg;
}

OutStream::~OutStream() {
	constexpr std::size_t buffLen = 1024;
	std::size_t size = 0;
	uint8_t buff[buffLen];
	writeMC(buff, buffLen, &m_msg, &size);
}

StdOutStream::StdOutStream(const char *file, int line, const char *ch, const char *msg) {
	m_msg.file = file;
	m_msg.line = line;
	m_msg.ch = ch;
	m_msg.msg = msg;
}

StdOutStream::~StdOutStream() {
#if defined(OX_USE_STDLIB)
	if (OxPrintTrace) {
		std::cout << std::setw(53) << std::left << m_msg.ch.c_str() << '|';
		std::cout << std::setw(65) << std::left << m_msg.msg.c_str() << '|';
		std::cout << " " << m_msg.file.c_str() << ':' << m_msg.line << "\n";
	}
#endif
}

void logError(const char *file, int line, Error err) {
	if (err) {
		ErrorInfo ei(err);
		TraceStream trc(file, line, "ox::error");
		trc <<  "Error:" << ei.errCode;
		if (ei.file != nullptr) {
			trc << "(" << reinterpret_cast<const char*>(ei.file) << ":" << ei.line << ")";
		}
	}
}

}
<|endoftext|>


<commit_before>// $Id$
//
//  Copyright (C) 2002-2006 Rational Discovery LLC
//
//   @@ All Rights Reserved  @@
//
#include <RDGeneral/FileParseException.h>
#include <RDGeneral/StreamOps.h>
#include <RDGeneral/RDLog.h>
#include <GraphMol/SanitException.h>

#include <boost/algorithm/string.hpp>
#include "MolSupplier.h"
#include "FileParsers.h"

#ifdef USEZIPSTREAM
// NOTE: As of this writing (1 Dec, 2004), this DOES NOT work)
#include <ZipStream/zipstream.hpp>
#endif
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>

namespace RDKit {

  std::string strip(const std::string &orig) {
    // FIX: this can be more efficeint
    // strip the end of line, white spaces and tabs
    std::string res = boost::trim_right_copy_if(orig,boost::is_any_of(" \t\r\n"));
    res = boost::trim_left_copy_if(res,boost::is_any_of(" \t\r\n"));
    return res;
  }

  SDMolSupplier::SDMolSupplier(const std::string &fileName, bool sanitize){
    init();
    // FIX: this binary moe of opening file is here because of a bug in VC++ 6.0
    // the function "tellg" does not work correctly if we do not open it this way
    // Need to check if this has been fixed in VC++ 7.0
    std::istream *tmpStream=0;
#ifdef USEZIPSTREAM
    if(fileName.find(".gz")==std::string::npos){
      tmpStream = static_cast<std::istream *>(new std::ifstream(fileName.c_str(), std::ios_base::binary));
      dp_streamHolder=0;
    } else {
      std::ifstream *ifStream_=new std::ifstream();
      ifStream_->open(fileName.c_str(),std::ios::in|std::ios_base::binary);
      tmpStream = static_cast<std::istream *>(new zlib_stream::zip_istream(*ifStream_));
      // we need to save this for later, otherwise the zipstream gets all
      // screwed up
      dp_streamHolder=ifStream_;
    }
#else
    tmpStream = static_cast<std::istream *>(new std::ifstream(fileName.c_str(), std::ios_base::binary));
#endif
    if (!tmpStream || (!(*tmpStream)) || (tmpStream->bad()) ) {
      std::ostringstream errout;
      errout << "Bad input file " << fileName;
      throw FileParseException(errout.str());
    }

    //dp_inStream = static_cast<std::istream *>(tmpStream);
    dp_inStream = tmpStream;
    df_owner=true;
    d_molpos.push_back(dp_inStream->tellg());
    df_sanitize = sanitize;
    this->checkForEnd();
    POSTCONDITION(dp_inStream,"bad instream");
  }

  void SDMolSupplier::init(){
    dp_inStream=0;
    df_owner = false;
    df_end = false;
    d_len = -1;
    d_last = 0;
    d_line = 0;
  }

  SDMolSupplier::~SDMolSupplier() {
    if (df_owner) {
      delete dp_inStream;
#ifdef USEZIPSTREAM
      if(dp_streamHolder) delete dp_streamHolder;
#endif
    }
  }

  void SDMolSupplier::setData(const std::string &text,
			      bool sanitize){
    if(dp_inStream && df_owner) delete dp_inStream;
    init();
    std::istream *tmpStream=0;
    tmpStream = static_cast<std::istream *>(new std::istringstream(text, std::ios_base::binary));
    dp_inStream = tmpStream;
    df_owner=true;
    d_molpos.push_back(dp_inStream->tellg());
    df_sanitize = sanitize;
    this->checkForEnd();
    POSTCONDITION(dp_inStream,"bad instream");
  }

  void SDMolSupplier::checkForEnd() {
    PRECONDITION(dp_inStream,"no stream");
    // we will call it end of file if we have more than 4 contiguous empty lines
    // or we reach end of file in the meantime
    if (dp_inStream->eof()) {
      df_end = true;
      d_len = d_molpos.size();
      return;
    }
    // we are not at the end of file, check for blank lines
    unsigned int nempty = 0;
    std::string tempStr, stmp;
    for (unsigned int i = 0; i < 4 ; i++) {
      tempStr = getLine(dp_inStream);
      if (dp_inStream->eof()) {
        df_end = true;
        d_len = d_molpos.size();
        return;
      }
      stmp = strip(tempStr);
      if (stmp.length() == 0) {
        nempty++;
      }
    }
    if (nempty == 4) {
      df_end = true;
      d_len = d_molpos.size();
    }
  }

  void SDMolSupplier::reset() {
    PRECONDITION(dp_inStream,"no stream");
    dp_inStream->clear();

    dp_inStream->seekg(0, std::ios::beg);
    df_end = false;
    d_last = 0;
    d_line = 0;
  }

  void SDMolSupplier::readMolProps(ROMol *mol){
    PRECONDITION(dp_inStream,"no stream");
    PRECONDITION(mol,"no molecule");
    std::string tempStr = getLine(dp_inStream);
    // FIX: report files missing the $$$$ marker
    while(!(dp_inStream->eof()) && tempStr.find("$$$$") != 0){
      tempStr = strip(tempStr);
      if(tempStr!=""){
        if (tempStr[0] == '>') { // data header line: start of a data item
            // ignore all other crap and seek for for a data label enclosed
            // by '<' and '>'
            // FIX: "CTfile.pdf" (page 51) says that the a data header line does not
            // have to contain a data label (instead can have something line field
            // id into a MACCS db). But we do not currently know what to do in this
            // situation - so ignore such data items for now
            tempStr.erase(0,1); // remover the first ">" sign
            int sl = tempStr.find("<"); // begin datalabel
            int se = tempStr.find(">"); // end datalabel
            if ((sl == -1) || (se == -1) || (se == (sl+1)) ) {
              // we either do not have a data label or the label is emtpy
              // no data label ignore until next data item
              // i.e. until we hit a blank line
              d_line++;
              tempStr = getLine(dp_inStream);
              std::string stmp = strip(tempStr);
              while (stmp.length() != 0) {
                d_line++;
                tempStr = getLine(dp_inStream);
                if(dp_inStream->eof()) throw FileParseException("End of data field name not found");
              }
            } else {
              std::string dlabel = tempStr.substr(sl+1, se-sl-1);
              // we know the label - now read in the relevant properties
              // until we hit a blank line
              d_line++;
              tempStr = getLine(dp_inStream);

              std::string prop;
              std::string stmp = strip(tempStr);
              int nplines = 0; // number of lines for this property
              while (stmp.length() != 0) {
                nplines++;
                if (nplines > 1) {
                  prop += "\n";
                }
                prop += tempStr;
                d_line++;
                tempStr = getLine(dp_inStream);
                stmp = strip(tempStr);
              }
              mol->setProp(dlabel, prop);
            }
        } else {
          // at this point we should always be at a line starting with '>'
          // following a blank line. If this is not true throw an exception
          // FIX: should we be deleting the molecule (which is probably fine)
          // because we couldn't read the data ???
          throw FileParseException("Problems encountered parsing data fields");
        }
      }
      d_line++;
      tempStr = getLine(dp_inStream);
    }
  }

  ROMol *SDMolSupplier::next() {
    PRECONDITION(dp_inStream,"no stream");
    // set the stream to the current position
    dp_inStream->seekg(d_molpos[d_last]);

    std::string tempStr;
    ROMol *res = NULL;
    // finally if we reached the end of the file set end to be true
    if (dp_inStream->eof()) {
      //FIX: we should probably be throwing an exception here
      df_end = true;
      d_len = d_molpos.size();
      return res;
    }

    std::string tempp;
    try {
      unsigned int line=d_line;
      res = MolDataStreamToMol(dp_inStream, line, df_sanitize);
      d_line= line+1;
      this->readMolProps(res);
    }
    catch (FileParseException &fe) {
      // we couldn't read a mol block or the data for the molecule. In this case
      // advance forward in the stream until we hit the next record and then rethrow
      // the exception. This should allow us to read the next molecule.
      BOOST_LOG(rdErrorLog) << "ERROR: on line " << d_line << " " << fe.message() << std::endl;
      BOOST_LOG(rdErrorLog) << "ERROR: moving to the begining of the next molecule\n";

      // FIX: report files missing the $$$$ marker
      while(!(dp_inStream->eof()) && tempStr.find("$$$$") != 0){
        d_line++;
        tempStr = getLine(dp_inStream);
      }
    }
    catch (MolSanitizeException &se) {
      // We couldn't sanitize a molecule we got - write out an error message and move to
      // the beginning of the next molecule
      BOOST_LOG(rdErrorLog) << "ERROR: Could not sanitize molecule ending on line " << d_line << std::endl;
      BOOST_LOG(rdErrorLog) << "ERROR: " << se.message() << "\n";
      while(!(dp_inStream->eof()) && tempStr.find("$$$$") != 0){
        d_line++;
        tempStr = getLine(dp_inStream);
      }
    } catch (...) {
      BOOST_LOG(rdErrorLog) << "Unexpected error hit on line " << d_line << std::endl;
      BOOST_LOG(rdErrorLog) << "ERROR: moving to the begining of the next molecule\n";
    }
    d_last++;
    unsigned int posHold=dp_inStream->tellg();
    this->checkForEnd();
    if (!this->df_end && d_last >= static_cast<int>(d_molpos.size())) {
      d_molpos.push_back(posHold);
    }

    return res;
  }

  void SDMolSupplier::moveTo(unsigned int idx) {
    PRECONDITION(dp_inStream,"no stream");
    CHECK_INVARIANT(idx >= 0, "");

    // move until we hit the desired idx
    if (idx < d_molpos.size() ) {
      dp_inStream->seekg(d_molpos[idx]);
      d_last = idx;
    }
    else {
      std::string tempStr;
      d_last = d_molpos.size() - 1;
      dp_inStream->seekg(d_molpos.back());
      while ((d_last < static_cast<int>(idx)) && (!dp_inStream->eof()) ) {
	   d_line++;
	   tempStr = getLine(dp_inStream);

	   if (tempStr.find("$$$$") == 0) {
	       d_molpos.push_back(dp_inStream->tellg());
	       d_last++;
	   }
      }
      // if we reached end of file without reaching "idx" we have an index error
      if (dp_inStream->eof()) {
    	d_len = d_molpos.size();
    	std::ostringstream errout;
    	errout << "ERROR: Index error (idx = " << idx  << ") : " << " we do no have enough mol blocks";
    	throw FileParseException(errout.str());
      }
    }
  }

  ROMol *SDMolSupplier::operator[](unsigned int idx) {
    PRECONDITION(dp_inStream,"no stream");
    // get the molecule with index idx
    moveTo(idx);
    return next();

  }

  unsigned int SDMolSupplier::length() {
    PRECONDITION(dp_inStream,"no stream");
    // return the number of mol blocks in the sdfile
    if (d_len > 0) {
      return d_len;
    }
    else {
      std::string tempStr;
      d_len = d_molpos.size();
      dp_inStream->seekg(d_molpos.back());
      while (!dp_inStream->eof()) {
	tempStr = getLine(dp_inStream);

	if (tempStr.find("$$$$") == 0) {
	  d_len++;
	}
      }
      // now remember to set the stream to the last postion we want to read
      dp_inStream->clear();
      dp_inStream->seekg(d_molpos[d_last]);
      return d_len;
    }
  }

  bool SDMolSupplier::atEnd() {
    PRECONDITION(dp_inStream,"no stream");
    return df_end;
  }

  void SDMolSupplier::setStreamIndices(const std::vector<std::streampos> &locs){
    d_molpos.clear();
    d_molpos.resize(locs.size());
    std::copy(locs.begin(),locs.end(),d_molpos.begin());
    this->reset();
    d_len = d_molpos.size();
  }
}

<commit_msg>minor cleanups... this seems to fix the memory corruption problems I found earlier, but there's no particular reason whey it should. http://sourceforge.net/tracker/index.php?func=detail&aid=1607290&group_id=160139&atid=814650<commit_after>// $Id$
//
//  Copyright (C) 2002-2006 Rational Discovery LLC
//
//   @@ All Rights Reserved  @@
//
#include <RDGeneral/FileParseException.h>
#include <RDGeneral/StreamOps.h>
#include <RDGeneral/RDLog.h>
#include <GraphMol/SanitException.h>

#include <boost/algorithm/string.hpp>
#include "MolSupplier.h"
#include "FileParsers.h"

#ifdef USEZIPSTREAM
// NOTE: As of this writing (1 Dec, 2004), this DOES NOT work)
#include <ZipStream/zipstream.hpp>
#endif
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>

namespace RDKit {

  std::string strip(const std::string &orig) {
    // FIX: this can be more efficeint
    // strip the end of line, white spaces and tabs
    std::string res = boost::trim_right_copy_if(orig,boost::is_any_of(" \t\r\n"));
    res = boost::trim_left_copy_if(res,boost::is_any_of(" \t\r\n"));
    return res;
  }

  SDMolSupplier::SDMolSupplier(const std::string &fileName, bool sanitize){
    init();
    // FIX: this binary moe of opening file is here because of a bug in VC++ 6.0
    // the function "tellg" does not work correctly if we do not open it this way
    // Need to check if this has been fixed in VC++ 7.0
    std::istream *tmpStream=0;
#ifdef USEZIPSTREAM
    if(fileName.find(".gz")==std::string::npos){
      tmpStream = static_cast<std::istream *>(new std::ifstream(fileName.c_str(), std::ios_base::binary));
      dp_streamHolder=0;
    } else {
      std::ifstream *ifStream_=new std::ifstream();
      ifStream_->open(fileName.c_str(),std::ios::in|std::ios_base::binary);
      tmpStream = static_cast<std::istream *>(new zlib_stream::zip_istream(*ifStream_));
      // we need to save this for later, otherwise the zipstream gets all
      // screwed up
      dp_streamHolder=ifStream_;
    }
#else
    tmpStream = static_cast<std::istream *>(new std::ifstream(fileName.c_str(), std::ios_base::binary));
#endif
    if (!tmpStream || (!(*tmpStream)) || (tmpStream->bad()) ) {
      std::ostringstream errout;
      errout << "Bad input file " << fileName;
      throw FileParseException(errout.str());
    }

    //dp_inStream = static_cast<std::istream *>(tmpStream);
    dp_inStream = tmpStream;
    df_owner=true;
    d_molpos.push_back(dp_inStream->tellg());
    df_sanitize = sanitize;
    this->checkForEnd();
    POSTCONDITION(dp_inStream,"bad instream");
  }

  void SDMolSupplier::init(){
    dp_inStream=0;
    df_owner = false;
    df_end = false;
    d_len = -1;
    d_last = 0;
    d_line = 0;
  }

  SDMolSupplier::~SDMolSupplier() {
    if (df_owner) {
      delete dp_inStream;
#ifdef USEZIPSTREAM
      if(dp_streamHolder) delete dp_streamHolder;
#endif
    }
  }

  void SDMolSupplier::setData(const std::string &text,
			      bool sanitize){
    if(dp_inStream && df_owner) delete dp_inStream;
    init();
    std::istream *tmpStream=0;
    tmpStream = static_cast<std::istream *>(new std::istringstream(text, std::ios_base::binary));
    dp_inStream = tmpStream;
    df_owner=true;
    d_molpos.push_back(dp_inStream->tellg());
    df_sanitize = sanitize;
    this->checkForEnd();
    POSTCONDITION(dp_inStream,"bad instream");
  }

  void SDMolSupplier::checkForEnd() {
    PRECONDITION(dp_inStream,"no stream");
    // we will call it end of file if we have more than 4 contiguous empty lines
    // or we reach end of file in the meantime
    if (dp_inStream->eof()) {
      df_end = true;
      d_len = d_molpos.size();
      return;
    }
    // we are not at the end of file, check for blank lines
    unsigned int nempty = 0;
    std::string tempStr, stmp;
    for (unsigned int i = 0; i < 4 ; i++) {
      tempStr = getLine(dp_inStream);
      if (dp_inStream->eof()) {
        df_end = true;
        d_len = d_molpos.size();
        return;
      }
      stmp = strip(tempStr);
      if (stmp.length() == 0) {
        nempty++;
      }
    }
    if (nempty == 4) {
      df_end = true;
      d_len = d_molpos.size();
    }
  }

  void SDMolSupplier::reset() {
    PRECONDITION(dp_inStream,"no stream");
    dp_inStream->clear();

    dp_inStream->seekg(0, std::ios::beg);
    df_end = false;
    d_last = 0;
    d_line = 0;
  }

  void SDMolSupplier::readMolProps(ROMol *mol){
    PRECONDITION(dp_inStream,"no stream");
    PRECONDITION(mol,"no molecule");
    std::string tempStr = getLine(dp_inStream);
    // FIX: report files missing the $$$$ marker
    while(!(dp_inStream->eof()) && tempStr.find("$$$$") != 0){
      tempStr = strip(tempStr);
      if(tempStr!=""){
        if (tempStr[0] == '>') { // data header line: start of a data item
            // ignore all other crap and seek for for a data label enclosed
            // by '<' and '>'
            // FIX: "CTfile.pdf" (page 51) says that the a data header line does not
            // have to contain a data label (instead can have something line field
            // id into a MACCS db). But we do not currently know what to do in this
            // situation - so ignore such data items for now
            tempStr.erase(0,1); // remover the first ">" sign
            int sl = tempStr.find("<"); // begin datalabel
            int se = tempStr.find(">"); // end datalabel
            if ((sl == -1) || (se == -1) || (se == (sl+1)) ) {
              // we either do not have a data label or the label is emtpy
              // no data label ignore until next data item
              // i.e. until we hit a blank line
              d_line++;
              tempStr = getLine(dp_inStream);
              std::string stmp = strip(tempStr);
              while (stmp.length() != 0) {
                d_line++;
                tempStr = getLine(dp_inStream);
                if(dp_inStream->eof()) throw FileParseException("End of data field name not found");
              }
            } else {
              std::string dlabel = tempStr.substr(sl+1, se-sl-1);
              // we know the label - now read in the relevant properties
              // until we hit a blank line
              d_line++;
              tempStr = getLine(dp_inStream);

              std::string prop;
              std::string stmp = strip(tempStr);
              int nplines = 0; // number of lines for this property
              while (stmp.length() != 0) {
                nplines++;
                if (nplines > 1) {
                  prop += "\n";
                }
                prop += tempStr;
                d_line++;
                tempStr = getLine(dp_inStream);
                stmp = strip(tempStr);
              }
              mol->setProp(dlabel, prop);
            }
        } else {
          // at this point we should always be at a line starting with '>'
          // following a blank line. If this is not true throw an exception
          // FIX: should we be deleting the molecule (which is probably fine)
          // because we couldn't read the data ???
          throw FileParseException("Problems encountered parsing data fields");
        }
      }
      d_line++;
      tempStr = getLine(dp_inStream);
    }
  }

  ROMol *SDMolSupplier::next() {
    PRECONDITION(dp_inStream,"no stream");
    // set the stream to the current position
    dp_inStream->seekg(d_molpos[d_last]);

    std::string tempStr;
    ROMol *res = NULL;
    // finally if we reached the end of the file set end to be true
    if (dp_inStream->eof()) {
      //FIX: we should probably be throwing an exception here
      df_end = true;
      d_len = d_molpos.size();
      return res;
    }

    std::string tempp;
    unsigned int line=d_line;
    try {
      //std::cerr << "mdstm" <<std::endl;
      res = MolDataStreamToMol(dp_inStream, line, df_sanitize);
      d_line= line+1;
      //std::cerr << "rmp" <<std::endl;
      this->readMolProps(res);
      //std::cerr << "d" <<std::endl;
    }
    catch (FileParseException &fe) {
      // we couldn't read a mol block or the data for the molecule. In this case
      // advance forward in the stream until we hit the next record and then rethrow
      // the exception. This should allow us to read the next molecule.
      BOOST_LOG(rdErrorLog) << "ERROR: on line " << d_line << " " << fe.message() << std::endl;
      BOOST_LOG(rdErrorLog) << "ERROR: moving to the begining of the next molecule\n";

      // FIX: report files missing the $$$$ marker
      while(!(dp_inStream->eof()) && tempStr.find("$$$$") != 0){
        d_line++;
        tempStr = getLine(dp_inStream);
      }
    }
    catch (MolSanitizeException &se) {
      // We couldn't sanitize a molecule we got - write out an error message and move to
      // the beginning of the next molecule
      BOOST_LOG(rdErrorLog) << "ERROR: Could not sanitize molecule ending on line " << d_line << std::endl;
      BOOST_LOG(rdErrorLog) << "ERROR: " << se.message() << "\n";
      while(!(dp_inStream->eof()) && tempStr.find("$$$$") != 0){
        d_line++;
        tempStr = getLine(dp_inStream);
      }
    } catch (...) {
      BOOST_LOG(rdErrorLog) << "Unexpected error hit on line " << line << std::endl;
      BOOST_LOG(rdErrorLog) << "ERROR: moving to the begining of the next molecule\n";
    }
    d_last++;
    unsigned int posHold=dp_inStream->tellg();
    this->checkForEnd();
    if (!this->df_end && d_last >= static_cast<int>(d_molpos.size())) {
      //std::cerr << "\tpos> " << posHold << std::endl;
      d_molpos.push_back(posHold);
    }

    return res;
  }

  void SDMolSupplier::moveTo(unsigned int idx) {
    PRECONDITION(dp_inStream,"no stream");
    CHECK_INVARIANT(idx >= 0, "");

    // move until we hit the desired idx
    if (idx < d_molpos.size() ) {
      dp_inStream->seekg(d_molpos[idx]);
      d_last = idx;
    }
    else {
      std::string tempStr;
      d_last = d_molpos.size() - 1;
      dp_inStream->seekg(d_molpos.back());
      while ((d_last < static_cast<int>(idx)) && (!dp_inStream->eof()) ) {
	   d_line++;
	   tempStr = getLine(dp_inStream);

	   if (tempStr.find("$$$$") == 0) {
	       d_molpos.push_back(dp_inStream->tellg());
	       d_last++;
	   }
      }
      // if we reached end of file without reaching "idx" we have an index error
      if (dp_inStream->eof()) {
    	d_len = d_molpos.size();
    	std::ostringstream errout;
    	errout << "ERROR: Index error (idx = " << idx  << ") : " << " we do no have enough mol blocks";
    	throw FileParseException(errout.str());
      }
    }
  }

  ROMol *SDMolSupplier::operator[](unsigned int idx) {
    PRECONDITION(dp_inStream,"no stream");
    // get the molecule with index idx
    moveTo(idx);
    return next();

  }

  unsigned int SDMolSupplier::length() {
    PRECONDITION(dp_inStream,"no stream");
    // return the number of mol blocks in the sdfile
    if (d_len > 0) {
      return d_len;
    }
    else {
      std::string tempStr;
      d_len = d_molpos.size();
      dp_inStream->seekg(d_molpos.back());
      while (!dp_inStream->eof()) {
	tempStr = getLine(dp_inStream);

	if (tempStr.find("$$$$") == 0) {
	  d_len++;
	}
      }
      // now remember to set the stream to the last postion we want to read
      dp_inStream->clear();
      dp_inStream->seekg(d_molpos[d_last]);
      return d_len;
    }
  }

  bool SDMolSupplier::atEnd() {
    PRECONDITION(dp_inStream,"no stream");
    return df_end;
  }

  void SDMolSupplier::setStreamIndices(const std::vector<std::streampos> &locs){
    d_molpos.clear();
    d_molpos.resize(locs.size());
    std::copy(locs.begin(),locs.end(),d_molpos.begin());
    this->reset();
    d_len = d_molpos.size();
  }
}

<|endoftext|>


<commit_before><commit_msg>Solution of (c) part of question 3.7 is complete and close issue #23<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "config.h"

#include "base/compiler_specific.h"

MSVC_PUSH_WARNING_LEVEL(0);
#include "ContextMenu.h"
#include "Document.h"
#include "DocumentLoader.h"
#include "Editor.h"
#include "FrameLoader.h"
#include "FrameView.h"
#include "HitTestResult.h"
#include "KURL.h"
#include "Widget.h"
MSVC_POP_WARNING();
#undef LOG

#include "webkit/glue/context_menu_client_impl.h"

#include "base/string_util.h"
#include "webkit/glue/context_node_types.h"
#include "webkit/glue/glue_util.h"
#include "webkit/glue/webdocumentloader_impl.h"
#include "webkit/glue/webview_impl.h"

#include "base/word_iterator.h"

// Helper function to determine whether text is a single word or a sentence.
static bool IsASingleWord(const std::wstring& text) {
  WordIterator iter(text, WordIterator::BREAK_WORD);
  int word_count = 0;
  if (!iter.Init()) return false;
  while (iter.Advance()) {
    if (iter.IsWord()) {
      word_count++;
      if (word_count > 1) // More than one word.
        return false;
    }
  }

  // Check for 0 words.
  if (!word_count)
    return false;

  // Has a single word.
  return true;
}

// Helper function to get misspelled word on which context menu
// is to be evolked. This function also sets the word on which context menu
// has been evoked to be the selected word, as required.
static std::wstring GetMisspelledWord(WebCore::ContextMenu* default_menu,
                                      WebCore::Frame* selected_frame) {
  std::wstring misspelled_word_string;

  // First select from selectedText to check for multiple word selection.
  misspelled_word_string = CollapseWhitespace(
      webkit_glue::StringToStdWString(selected_frame->selectedText()),
      false);

  // Don't provide suggestions for multiple words.
  if (!misspelled_word_string.empty() &&
      !IsASingleWord(misspelled_word_string))
    return L"";

  // Expand around the click to see if we clicked a word.
  WebCore::Selection selection;
  WebCore::VisiblePosition pos(default_menu->hitTestResult().innerNode()->
      renderer()->positionForPoint(default_menu->hitTestResult().
                                   localPoint()));

  if (pos.isNotNull()) {
    selection = WebCore::Selection(pos);
    selection.expandUsingGranularity(WebCore::WordGranularity);
  }

  if (selection.isRange()) {
    selected_frame->setSelectionGranularity(WebCore::WordGranularity);
  }

  if (selected_frame->shouldChangeSelection(selection))
    selected_frame->selection()->setSelection(selection);

  misspelled_word_string = CollapseWhitespace(
      webkit_glue::StringToStdWString(selected_frame->selectedText()),
                                      false);

  return misspelled_word_string;
}

ContextMenuClientImpl::~ContextMenuClientImpl() {
}

void ContextMenuClientImpl::contextMenuDestroyed() {
  delete this;
}

// Figure out the URL of a page or subframe. Returns |page_type| as the type,
// which indicates page or subframe, or ContextNode::NONE if the URL could not
// be determined for some reason.
static ContextNode::Type GetTypeAndURLFromFrame(WebCore::Frame* frame,
                                                GURL* url,
                                                ContextNode::Type page_type) {
  ContextNode::Type type = ContextNode::NONE;
  if (frame) {
    WebCore::DocumentLoader* dl = frame->loader()->documentLoader();
    if (dl) {
      WebDataSource* ds = static_cast<WebDocumentLoaderImpl*>(dl)->
          GetDataSource();
      if (ds) {
        type = page_type;
        *url = ds->HasUnreachableURL() ? ds->GetUnreachableURL()
                                       : ds->GetRequest().GetURL();
      }
    }
  }
  return type;
}

WebCore::PlatformMenuDescription
    ContextMenuClientImpl::getCustomMenuFromDefaultItems(
        WebCore::ContextMenu* default_menu) {
  // Displaying the context menu in this function is a big hack as we don't
  // have context, i.e. whether this is being invoked via a script or in
  // response to user input (Mouse event WM_RBUTTONDOWN,
  // Keyboard events KeyVK_APPS, Shift+F10). Check if this is being invoked
  // in response to the above input events before popping up the context menu.
  if (!webview_->context_menu_allowed())
    return NULL;

  WebCore::HitTestResult r = default_menu->hitTestResult();
  WebCore::Frame* selected_frame = r.innerNonSharedNode()->document()->frame();

  WebCore::IntPoint menu_point =
      selected_frame->view()->contentsToWindow(r.point());

  ContextNode::Type type = ContextNode::NONE;

  // Links, Images and Image-Links take preference over all else.
  WebCore::KURL link_url = r.absoluteLinkURL();
  if (!link_url.isEmpty()) {
    type = ContextNode::LINK;
  }
  WebCore::KURL image_url = r.absoluteImageURL();
  if (!image_url.isEmpty()) {
    type = ContextNode::IMAGE;
  }
  if (!image_url.isEmpty() && !link_url.isEmpty())
    type = ContextNode::IMAGE_LINK;

  // If it's not a link, an image or an image link, show a selection menu or a
  // more generic page menu.
  std::wstring selection_text_string;
  std::wstring misspelled_word_string;
  GURL frame_url;
  GURL page_url;
  std::string security_info;

  std::wstring frame_encoding;
  // Send the frame and page URLs in any case.
  ContextNode::Type frame_type = ContextNode::NONE;
  ContextNode::Type page_type =
      GetTypeAndURLFromFrame(webview_->main_frame()->frame(),
                             &page_url,
                             ContextNode::PAGE);
  if (selected_frame != webview_->main_frame()->frame()) {
    frame_type = GetTypeAndURLFromFrame(selected_frame,
                                        &frame_url,
                                        ContextNode::FRAME);
    frame_encoding = webkit_glue::StringToStdWString(
        selected_frame->loader()->encoding());
  }

  if (type == ContextNode::NONE) {
    if (r.isContentEditable()) {
      type = ContextNode::EDITABLE;
      if (webview_->FocusedFrameNeedsSpellchecking()) {
        misspelled_word_string = GetMisspelledWord(default_menu,
                                                   selected_frame);
      }
    } else if (r.isSelected()) {
      type = ContextNode::SELECTION;
      selection_text_string =
          CollapseWhitespace(
              webkit_glue::StringToStdWString(selected_frame->selectedText()),
              false);
    } else if (selected_frame != webview_->main_frame()->frame()) {
      type = frame_type;
    } else {
      type = page_type;
    }
  }

  // Now retrieve the security info.
  WebCore::DocumentLoader* dl = selected_frame->loader()->documentLoader();
  if (dl) {
    WebDataSource* ds = static_cast<WebDocumentLoaderImpl*>(dl)->
        GetDataSource();
    if (ds) {
      const WebResponse& response = ds->GetResponse();
      security_info = response.GetSecurityInfo();
    }
  }

  int edit_flags = ContextNode::CAN_DO_NONE;
  if (webview_->GetFocusedWebCoreFrame()->editor()->canUndo())
    edit_flags |= ContextNode::CAN_UNDO;
  if (webview_->GetFocusedWebCoreFrame()->editor()->canRedo())
    edit_flags |= ContextNode::CAN_REDO;
  if (webview_->GetFocusedWebCoreFrame()->editor()->canCut())
    edit_flags |= ContextNode::CAN_CUT;
  if (webview_->GetFocusedWebCoreFrame()->editor()->canCopy())
    edit_flags |= ContextNode::CAN_COPY;
  if (webview_->GetFocusedWebCoreFrame()->editor()->canPaste())
    edit_flags |= ContextNode::CAN_PASTE;
  if (webview_->GetFocusedWebCoreFrame()->editor()->canDelete())
    edit_flags |= ContextNode::CAN_DELETE;
  // We can always select all...
  edit_flags |= ContextNode::CAN_SELECT_ALL;

  WebViewDelegate* d = webview_->delegate();
  if (d) {
    d->ShowContextMenu(webview_,
                       type,
                       menu_point.x(),
                       menu_point.y(),
                       webkit_glue::KURLToGURL(link_url),
                       webkit_glue::KURLToGURL(image_url),
                       page_url,
                       frame_url,
                       selection_text_string,
                       misspelled_word_string,
                       edit_flags,
                       security_info);
  }
  return NULL;
}

void ContextMenuClientImpl::contextMenuItemSelected(
    WebCore::ContextMenuItem*, const WebCore::ContextMenu*) {
}

void ContextMenuClientImpl::downloadURL(const WebCore::KURL&) {
}

void ContextMenuClientImpl::copyImageToClipboard(const WebCore::HitTestResult&) {
}

void ContextMenuClientImpl::searchWithGoogle(const WebCore::Frame*) {
}

void ContextMenuClientImpl::lookUpInDictionary(WebCore::Frame*) {
}

void ContextMenuClientImpl::speak(const WebCore::String&) {
}

void ContextMenuClientImpl::stopSpeaking() {
}

bool ContextMenuClientImpl::shouldIncludeInspectElementItem() {
    return false;  // TODO(jackson): Eventually include the inspector context menu item
}

#if defined(OS_MACOSX)
void ContextMenuClientImpl::searchWithSpotlight() {
  // TODO(pinkerton): write this
}
#endif
<commit_msg>When right clicking in a text area that is scrolled, the wrong word is selected.  This is because we use the wrong node when getting the selection.  We want to use the shadow inner node, but the hit test result provided to the ContextMenu is not the shadow node.  To work around this, we recompute the hit test result.<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "config.h"

#include "base/compiler_specific.h"

MSVC_PUSH_WARNING_LEVEL(0);
#include "ContextMenu.h"
#include "Document.h"
#include "DocumentLoader.h"
#include "Editor.h"
#include "EventHandler.h"
#include "FrameLoader.h"
#include "FrameView.h"
#include "HitTestResult.h"
#include "KURL.h"
#include "Widget.h"
MSVC_POP_WARNING();
#undef LOG

#include "webkit/glue/context_menu_client_impl.h"

#include "base/string_util.h"
#include "webkit/glue/context_node_types.h"
#include "webkit/glue/glue_util.h"
#include "webkit/glue/webdocumentloader_impl.h"
#include "webkit/glue/webview_impl.h"

#include "base/word_iterator.h"

namespace {

// Helper function to determine whether text is a single word or a sentence.
bool IsASingleWord(const std::wstring& text) {
  WordIterator iter(text, WordIterator::BREAK_WORD);
  int word_count = 0;
  if (!iter.Init()) return false;
  while (iter.Advance()) {
    if (iter.IsWord()) {
      word_count++;
      if (word_count > 1) // More than one word.
        return false;
    }
  }

  // Check for 0 words.
  if (!word_count)
    return false;

  // Has a single word.
  return true;
}

// Helper function to get misspelled word on which context menu
// is to be evolked. This function also sets the word on which context menu
// has been evoked to be the selected word, as required.
std::wstring GetMisspelledWord(const WebCore::ContextMenu* default_menu,
                               WebCore::Frame* selected_frame) {
  std::wstring misspelled_word_string;

  // First select from selectedText to check for multiple word selection.
  misspelled_word_string = CollapseWhitespace(
      webkit_glue::StringToStdWString(selected_frame->selectedText()),
      false);

  // Don't provide suggestions for multiple words.
  if (!misspelled_word_string.empty() &&
      !IsASingleWord(misspelled_word_string))
    return L"";

  // Expand around the click to see if we clicked a word.
  WebCore::Node* inner_node = default_menu->hitTestResult().innerNode();
  if (inner_node->renderer()->isTextArea()) {
    WebCore::HitTestResult real_result = selected_frame->eventHandler()->
        hitTestResultAtPoint(default_menu->hitTestResult().localPoint(), true);
    inner_node = real_result.innerNode();
  }

  WebCore::VisiblePosition pos(inner_node->renderer()->
      positionForPoint(default_menu->hitTestResult().localPoint()));

  WebCore::Selection selection;
  if (pos.isNotNull()) {
    selection = WebCore::Selection(pos);
    selection.expandUsingGranularity(WebCore::WordGranularity);
  }

  if (selection.isRange()) {
    selected_frame->setSelectionGranularity(WebCore::WordGranularity);
  }

  if (selected_frame->shouldChangeSelection(selection))
    selected_frame->selection()->setSelection(selection);

  misspelled_word_string = CollapseWhitespace(
      webkit_glue::StringToStdWString(selected_frame->selectedText()),
                                      false);

  return misspelled_word_string;
}

}  // namespace

ContextMenuClientImpl::~ContextMenuClientImpl() {
}

void ContextMenuClientImpl::contextMenuDestroyed() {
  delete this;
}

// Figure out the URL of a page or subframe. Returns |page_type| as the type,
// which indicates page or subframe, or ContextNode::NONE if the URL could not
// be determined for some reason.
static ContextNode::Type GetTypeAndURLFromFrame(WebCore::Frame* frame,
                                                GURL* url,
                                                ContextNode::Type page_type) {
  ContextNode::Type type = ContextNode::NONE;
  if (frame) {
    WebCore::DocumentLoader* dl = frame->loader()->documentLoader();
    if (dl) {
      WebDataSource* ds = static_cast<WebDocumentLoaderImpl*>(dl)->
          GetDataSource();
      if (ds) {
        type = page_type;
        *url = ds->HasUnreachableURL() ? ds->GetUnreachableURL()
                                       : ds->GetRequest().GetURL();
      }
    }
  }
  return type;
}

WebCore::PlatformMenuDescription
    ContextMenuClientImpl::getCustomMenuFromDefaultItems(
        WebCore::ContextMenu* default_menu) {
  // Displaying the context menu in this function is a big hack as we don't
  // have context, i.e. whether this is being invoked via a script or in
  // response to user input (Mouse event WM_RBUTTONDOWN,
  // Keyboard events KeyVK_APPS, Shift+F10). Check if this is being invoked
  // in response to the above input events before popping up the context menu.
  if (!webview_->context_menu_allowed())
    return NULL;

  WebCore::HitTestResult r = default_menu->hitTestResult();
  WebCore::Frame* selected_frame = r.innerNonSharedNode()->document()->frame();

  WebCore::IntPoint menu_point =
      selected_frame->view()->contentsToWindow(r.point());

  ContextNode::Type type = ContextNode::NONE;

  // Links, Images and Image-Links take preference over all else.
  WebCore::KURL link_url = r.absoluteLinkURL();
  if (!link_url.isEmpty()) {
    type = ContextNode::LINK;
  }
  WebCore::KURL image_url = r.absoluteImageURL();
  if (!image_url.isEmpty()) {
    type = ContextNode::IMAGE;
  }
  if (!image_url.isEmpty() && !link_url.isEmpty())
    type = ContextNode::IMAGE_LINK;

  // If it's not a link, an image or an image link, show a selection menu or a
  // more generic page menu.
  std::wstring selection_text_string;
  std::wstring misspelled_word_string;
  GURL frame_url;
  GURL page_url;
  std::string security_info;

  std::wstring frame_encoding;
  // Send the frame and page URLs in any case.
  ContextNode::Type frame_type = ContextNode::NONE;
  ContextNode::Type page_type =
      GetTypeAndURLFromFrame(webview_->main_frame()->frame(),
                             &page_url,
                             ContextNode::PAGE);
  if (selected_frame != webview_->main_frame()->frame()) {
    frame_type = GetTypeAndURLFromFrame(selected_frame,
                                        &frame_url,
                                        ContextNode::FRAME);
    frame_encoding = webkit_glue::StringToStdWString(
        selected_frame->loader()->encoding());
  }

  if (type == ContextNode::NONE) {
    if (r.isContentEditable()) {
      type = ContextNode::EDITABLE;
      if (webview_->FocusedFrameNeedsSpellchecking()) {
        misspelled_word_string = GetMisspelledWord(default_menu,
                                                   selected_frame);
      }
    } else if (r.isSelected()) {
      type = ContextNode::SELECTION;
      selection_text_string =
          CollapseWhitespace(
              webkit_glue::StringToStdWString(selected_frame->selectedText()),
              false);
    } else if (selected_frame != webview_->main_frame()->frame()) {
      type = frame_type;
    } else {
      type = page_type;
    }
  }

  // Now retrieve the security info.
  WebCore::DocumentLoader* dl = selected_frame->loader()->documentLoader();
  if (dl) {
    WebDataSource* ds = static_cast<WebDocumentLoaderImpl*>(dl)->
        GetDataSource();
    if (ds) {
      const WebResponse& response = ds->GetResponse();
      security_info = response.GetSecurityInfo();
    }
  }

  int edit_flags = ContextNode::CAN_DO_NONE;
  if (webview_->GetFocusedWebCoreFrame()->editor()->canUndo())
    edit_flags |= ContextNode::CAN_UNDO;
  if (webview_->GetFocusedWebCoreFrame()->editor()->canRedo())
    edit_flags |= ContextNode::CAN_REDO;
  if (webview_->GetFocusedWebCoreFrame()->editor()->canCut())
    edit_flags |= ContextNode::CAN_CUT;
  if (webview_->GetFocusedWebCoreFrame()->editor()->canCopy())
    edit_flags |= ContextNode::CAN_COPY;
  if (webview_->GetFocusedWebCoreFrame()->editor()->canPaste())
    edit_flags |= ContextNode::CAN_PASTE;
  if (webview_->GetFocusedWebCoreFrame()->editor()->canDelete())
    edit_flags |= ContextNode::CAN_DELETE;
  // We can always select all...
  edit_flags |= ContextNode::CAN_SELECT_ALL;

  WebViewDelegate* d = webview_->delegate();
  if (d) {
    d->ShowContextMenu(webview_,
                       type,
                       menu_point.x(),
                       menu_point.y(),
                       webkit_glue::KURLToGURL(link_url),
                       webkit_glue::KURLToGURL(image_url),
                       page_url,
                       frame_url,
                       selection_text_string,
                       misspelled_word_string,
                       edit_flags,
                       security_info);
  }
  return NULL;
}

void ContextMenuClientImpl::contextMenuItemSelected(
    WebCore::ContextMenuItem*, const WebCore::ContextMenu*) {
}

void ContextMenuClientImpl::downloadURL(const WebCore::KURL&) {
}

void ContextMenuClientImpl::copyImageToClipboard(const WebCore::HitTestResult&) {
}

void ContextMenuClientImpl::searchWithGoogle(const WebCore::Frame*) {
}

void ContextMenuClientImpl::lookUpInDictionary(WebCore::Frame*) {
}

void ContextMenuClientImpl::speak(const WebCore::String&) {
}

void ContextMenuClientImpl::stopSpeaking() {
}

bool ContextMenuClientImpl::shouldIncludeInspectElementItem() {
    return false;  // TODO(jackson): Eventually include the inspector context menu item
}

#if defined(OS_MACOSX)
void ContextMenuClientImpl::searchWithSpotlight() {
  // TODO(pinkerton): write this
}
#endif
<|endoftext|>