<commit_before>// Copyright (c) 2009 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 <stdio.h>
#include <stdlib.h>
#include <new>

#include "third_party/skia/include/core/SkTypes.h"

// This implementation of sk_malloc_flags() and friends is identical
// to SkMemory_malloc.c, except that it disables the CRT's new_handler
// during malloc(), when SK_MALLOC_THROW is not set (ie., when
// sk_malloc_flags() would not abort on NULL).

void sk_throw() {
    SkASSERT(!"sk_throw");
    abort();
}

void sk_out_of_memory(void) {
    SkASSERT(!"sk_out_of_memory");
    abort();
}

void* sk_malloc_throw(size_t size) {
    return sk_malloc_flags(size, SK_MALLOC_THROW);
}

void* sk_realloc_throw(void* addr, size_t size) {
    void* p = realloc(addr, size);
    if (size == 0) {
        return p;
    }
    if (p == NULL) {
        sk_throw();
    }
    return p;
}

void sk_free(void* p) {
    if (p) {
        free(p);
    }
}

void* sk_malloc_flags(size_t size, unsigned flags) {
    std::new_handler old_handler;
    if (!(flags & SK_MALLOC_THROW)) {
      old_handler = std::set_new_handler(NULL);
    }
    void* p = malloc(size);
    if (!(flags & SK_MALLOC_THROW)) {
      std::set_new_handler(old_handler);
    }
    if (p == NULL) {
        if (flags & SK_MALLOC_THROW) {
            sk_throw();
        }
    }
    return p;
}

<commit_msg>Fix for Skia data race.  This may introduce some performance issues; will watch perf bots carefully.<commit_after>// Copyright (c) 2009 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 <stdio.h>
#include <stdlib.h>
#include <new>

#include "third_party/skia/include/core/SkTypes.h"
#include "third_party/skia/include/core/SkThread.h"

// This implementation of sk_malloc_flags() and friends is identical
// to SkMemory_malloc.c, except that it disables the CRT's new_handler
// during malloc(), when SK_MALLOC_THROW is not set (ie., when
// sk_malloc_flags() would not abort on NULL).

static SkMutex gSkNewHandlerMutex;

void sk_throw() {
    SkASSERT(!"sk_throw");
    abort();
}

void sk_out_of_memory(void) {
    SkASSERT(!"sk_out_of_memory");
    abort();
}

void* sk_malloc_throw(size_t size) {
    return sk_malloc_flags(size, SK_MALLOC_THROW);
}

void* sk_realloc_throw(void* addr, size_t size) {
    void* p = realloc(addr, size);
    if (size == 0) {
        return p;
    }
    if (p == NULL) {
        sk_throw();
    }
    return p;
}

void sk_free(void* p) {
    if (p) {
        free(p);
    }
}

void* sk_malloc_flags(size_t size, unsigned flags) {
    void* p;
    if (!(flags & SK_MALLOC_THROW)) {
      SkAutoMutexAcquire lock(gSkNewHandlerMutex);
      std::new_handler old_handler = std::set_new_handler(NULL);
      p = malloc(size);
      std::set_new_handler(old_handler);
    } else {
      p = malloc(size);
    }
    if (p == NULL) {
        if (flags & SK_MALLOC_THROW) {
            sk_throw();
        }
    }
    return p;
}

<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "parser/TypeGrammar.hpp"
#include "lexer/position.hpp"

using namespace eddic;

parser::TypeGrammar::TypeGrammar(const lexer::Lexer& lexer, const lexer::pos_iterator_type& position_begin) :
        TypeGrammar::base_type(type, "Type Grammar"),
        position_begin(position_begin){

    const_ %=
            (lexer.const_ > boost::spirit::attr(true))
        |   boost::spirit::attr(false);

    array_type %=
            qi::eps
        >>  lexer.identifier
        >>  lexer.left_bracket
        >>  lexer.right_bracket;

    pointer_type %=
            qi::eps
        >>  lexer.identifier
        >>  lexer.multiplication;

    simple_type %=
            qi::eps
        >>  const_
        >>  lexer.identifier;

    type %=
            array_type
        |   pointer_type
        |   simple_type;
}
<commit_msg>Cleanup<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "parser/TypeGrammar.hpp"
#include "lexer/position.hpp"

using namespace eddic;

parser::TypeGrammar::TypeGrammar(const lexer::Lexer& lexer, const lexer::pos_iterator_type& position_begin) :
        TypeGrammar::base_type(type, "Type Grammar"),
        position_begin(position_begin){

    const_ %=
            (lexer.const_ > boost::spirit::attr(true))
        |   boost::spirit::attr(false);

    array_type %=
            lexer.identifier
        >>  lexer.left_bracket
        >>  lexer.right_bracket;

    pointer_type %=
            lexer.identifier
        >>  lexer.multiplication;

    simple_type %=
            const_
        >>  lexer.identifier;

    type %=
            array_type
        |   pointer_type
        |   simple_type;
}
<|endoftext|>


<commit_before>//
//  remapped_symbol_set.cpp
//  Parse
//
//  Created by Andrew Hunter on 26/04/2011.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#include <iostream>
#include <map>
#include <set>

#include "remapped_symbol_map.h"
#include "range.h"

using namespace std;
using namespace dfa;

/// \brief Empty symbol set
const remapped_symbol_map::new_symbols remapped_symbol_map::s_NoSymbols;

/// \brief Generates an empty remapped symbol map
remapped_symbol_map::remapped_symbol_map() {
}

/// \brief Copy constructor
remapped_symbol_map::remapped_symbol_map(const remapped_symbol_map& copyFrom)
: m_OldToNew(copyFrom.m_OldToNew) {
}

/// \brief Finds or adds an identifier for the specified symbol, adding the specified set of new symbols as the new symbols
int remapped_symbol_map::identifier_for_symbols(const symbol_set& symbols, const new_symbols& newSymbols) {
    // Get the set ID for these symbols
    int setId = symbol_map::identifier_for_symbols(symbols);

    // Try to look up the existing set
    old_to_new_map::iterator existing = m_OldToNew.find(setId);

    if (existing == m_OldToNew.end()) {
        // Just add these symbols
        m_OldToNew[setId] = newSymbols;
    } else {
        // Merge the sets
        for (new_symbols::iterator it = newSymbols.begin(); it != newSymbols.end(); it++) {
            existing->second.insert(*it);
        }
    }

    // Return this as the result
    return setId;
}

/// \brief Range of symbols
typedef range<int> symbol_range;

/// \brief Type mapping symbol ranges to the sets that contain them
typedef map<symbol_range, set<int>, symbol_range::sort_by_lower > sets_for_range;

/// \brief Splits a range that exists in sets into two.
///
/// We end up with two ranges: lower..splitPoint and splitPoint..upper
/// Returns an iterator for the start of the new ranges
static sets_for_range::iterator split(sets_for_range& sets, symbol_range original, int splitPoint) {
    // Get the values for this range
    set<int> values = sets[original];

    // Remove the original range
    sets.erase(original);

    // Create the split ranges
    sets[symbol_range(splitPoint, original.upper())] = values;
    sets_for_range::iterator result = sets.insert(sets_for_range::value_type(symbol_range(original.lower(), splitPoint), values)).first;
    return result;
}

/// \brief Adds the ranges in a particular symbol set
static void add_set(sets_for_range& sets, const symbol_set& symbols, int identifier) {
    // Iterate through the ranges in this set
    for (symbol_set::iterator range = symbols.begin(); range != symbols.end(); range++) {
        // Find the first item in the set whose lower bound is >= this range
        sets_for_range::iterator firstGreaterThan = sets.lower_bound(*range);

        // If this isn't at the beginning, then it's possible that this set overlaps the preceeding set
        if (firstGreaterThan != sets.begin()) {
            // Get the previous set
            sets_for_range::iterator preceeding = firstGreaterThan;
            preceeding--;

            // See if there's an overlap
            if (preceeding->first.upper() >= range->lower()) {
                // Start from the preceeding set if they do
                firstGreaterThan = preceeding;
            }
        }

        // If we're at the end of the list here, then this is an entirely new range
        // This is also a new range if the item at firstGreaterThan doesn't overlap the range
        // Finally, we can just add to the set for a particular range if we get an exact match
        if (firstGreaterThan == sets.end() || !firstGreaterThan->first.overlaps(*range) || firstGreaterThan->first == *range) {
            // Just add this range
            sets[*range].insert(identifier);
            continue;
        }

        // We've got some overlap, but it's not exact
        symbol_range    remaining = *range;                 // Range of characters remaining to merge in
        set<int>        justUs;                             // Set containing only the new identifier

        justUs.insert(identifier);

        while (remaining.upper() != remaining.lower()) {
            cout << "Remaining: " << remaining.lower() << "-" << remaining.upper() << endl;
            cout << "Sets:";
            for (sets_for_range::iterator it = sets.begin(); it != sets.end(); it++) {
                cout << " " << it->first.lower() << "-" << it->first.upper();
            }
            cout << endl;
            if (firstGreaterThan == sets.end()) cout << "At end" << endl;
            else cout << "Position: " << firstGreaterThan->first.lower() << "-" << firstGreaterThan->first.upper() << endl;

            // If we're at the end, we can just add the remaining set and stop
            if (firstGreaterThan == sets.end()) {
                sets[remaining] = justUs;
                break;
            }

            // If there's a gap between the remaining set and the current position, then fill it in
            if (firstGreaterThan->first.lower() > remaining.lower()) {
                int newUpper = firstGreaterThan->first.lower();

                // Insert a value to fill the gap
                firstGreaterThan = sets.insert(firstGreaterThan, sets_for_range::value_type(symbol_range(remaining.lower(), newUpper), justUs));

                // Adjust the remaining set
                remaining = symbol_range(newUpper, remaining.upper());

                // Want the value after the one we just inserted
                firstGreaterThan++;

                // Start again
                continue;
            }

            // If there's a gap between the lowest point in the range we're currently splitting and the current range, then split there
            if (firstGreaterThan->first.lower() < remaining.lower()) {
                // Split the ranges and move so that the lowest point matches
                firstGreaterThan = split(sets, firstGreaterThan->first, remaining.lower());
                firstGreaterThan++;
            }

            // If the current range ends beyond the end of the remaining set, then split it
            if (firstGreaterThan->first.upper() > remaining.upper()) {
                firstGreaterThan = split(sets, firstGreaterThan->first, remaining.upper());
            }

            // Current range should overlap the range specified by firstGreaterThan: add this identifier
            firstGreaterThan->second.insert(identifier);

            // Adjust the remaining set
            remaining = symbol_range(firstGreaterThan->first.upper(), remaining.upper());

            // Move on
            firstGreaterThan++;
        }

        cout << "Done adding" << endl;
        cout << "Sets:";
        for (sets_for_range::iterator it = sets.begin(); it != sets.end(); it++) {
            cout << " " << it->first.lower() << "-" << it->first.upper();
        }
        cout << endl;
    }
}

/// \brief Factory method that generates a remapped symbol map by removing duplicates
///
/// This finds all the symbol sets that overlap in the original, and splits them up so that any given symbol is only in one set.
/// It sets up the remapping so it is possible to find the new set IDs for any symbol set in the original.
remapped_symbol_map* remapped_symbol_map::deduplicate(const symbol_map& source) {
    // Map of symbol ranges to the symbol sets in the original that contain them
    sets_for_range setsContainingRange;

    // Iterate through the sets in the source
    for (symbol_map::iterator symSet = source.begin(); symSet != source.end(); symSet++) {
        // Add this into the sets containing this range
        add_set(setsContainingRange, symSet->first, symSet->second);
    }

    // Create the result
    remapped_symbol_map* newSet = new remapped_symbol_map();

    // Create a new set for each range we got in the previous step
    for (sets_for_range::iterator it = setsContainingRange.begin(); it != setsContainingRange.end(); it++) {
        newSet->identifier_for_symbols(it->first, it->second);
    }

    // This is the result
    return newSet;
}
<commit_msg>Removed debugging code<commit_after>//
//  remapped_symbol_set.cpp
//  Parse
//
//  Created by Andrew Hunter on 26/04/2011.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#include <iostream>
#include <map>
#include <set>

#include "remapped_symbol_map.h"
#include "range.h"

using namespace std;
using namespace dfa;

/// \brief Empty symbol set
const remapped_symbol_map::new_symbols remapped_symbol_map::s_NoSymbols;

/// \brief Generates an empty remapped symbol map
remapped_symbol_map::remapped_symbol_map() {
}

/// \brief Copy constructor
remapped_symbol_map::remapped_symbol_map(const remapped_symbol_map& copyFrom)
: m_OldToNew(copyFrom.m_OldToNew) {
}

/// \brief Finds or adds an identifier for the specified symbol, adding the specified set of new symbols as the new symbols
int remapped_symbol_map::identifier_for_symbols(const symbol_set& symbols, const new_symbols& newSymbols) {
    // Get the set ID for these symbols
    int setId = symbol_map::identifier_for_symbols(symbols);

    // Try to look up the existing set
    old_to_new_map::iterator existing = m_OldToNew.find(setId);

    if (existing == m_OldToNew.end()) {
        // Just add these symbols
        m_OldToNew[setId] = newSymbols;
    } else {
        // Merge the sets
        for (new_symbols::iterator it = newSymbols.begin(); it != newSymbols.end(); it++) {
            existing->second.insert(*it);
        }
    }

    // Return this as the result
    return setId;
}

/// \brief Range of symbols
typedef range<int> symbol_range;

/// \brief Type mapping symbol ranges to the sets that contain them
typedef map<symbol_range, set<int>, symbol_range::sort_by_lower > sets_for_range;

/// \brief Splits a range that exists in sets into two.
///
/// We end up with two ranges: lower..splitPoint and splitPoint..upper
/// Returns an iterator for the start of the new ranges
static sets_for_range::iterator split(sets_for_range& sets, symbol_range original, int splitPoint) {
    // Get the values for this range
    set<int> values = sets[original];

    // Remove the original range
    sets.erase(original);

    // Create the split ranges
    sets[symbol_range(splitPoint, original.upper())] = values;
    sets_for_range::iterator result = sets.insert(sets_for_range::value_type(symbol_range(original.lower(), splitPoint), values)).first;
    return result;
}

/// \brief Adds the ranges in a particular symbol set
static void add_set(sets_for_range& sets, const symbol_set& symbols, int identifier) {
    // Iterate through the ranges in this set
    for (symbol_set::iterator range = symbols.begin(); range != symbols.end(); range++) {
        // Find the first item in the set whose lower bound is >= this range
        sets_for_range::iterator firstGreaterThan = sets.lower_bound(*range);

        // If this isn't at the beginning, then it's possible that this set overlaps the preceeding set
        if (firstGreaterThan != sets.begin()) {
            // Get the previous set
            sets_for_range::iterator preceeding = firstGreaterThan;
            preceeding--;

            // See if there's an overlap
            if (preceeding->first.upper() >= range->lower()) {
                // Start from the preceeding set if they do
                firstGreaterThan = preceeding;
            }
        }

        // If we're at the end of the list here, then this is an entirely new range
        // This is also a new range if the item at firstGreaterThan doesn't overlap the range
        // Finally, we can just add to the set for a particular range if we get an exact match
        if (firstGreaterThan == sets.end() || !firstGreaterThan->first.overlaps(*range) || firstGreaterThan->first == *range) {
            // Just add this range
            sets[*range].insert(identifier);
            continue;
        }

        // We've got some overlap, but it's not exact
        symbol_range    remaining = *range;                 // Range of characters remaining to merge in
        set<int>        justUs;                             // Set containing only the new identifier

        justUs.insert(identifier);

        while (remaining.upper() != remaining.lower()) {
            // If we're at the end, we can just add the remaining set and stop
            if (firstGreaterThan == sets.end()) {
                sets[remaining] = justUs;
                break;
            }

            // If there's a gap between the remaining set and the current position, then fill it in
            if (firstGreaterThan->first.lower() > remaining.lower()) {
                int newUpper = firstGreaterThan->first.lower();

                // Insert a value to fill the gap
                firstGreaterThan = sets.insert(firstGreaterThan, sets_for_range::value_type(symbol_range(remaining.lower(), newUpper), justUs));

                // Adjust the remaining set
                remaining = symbol_range(newUpper, remaining.upper());

                // Want the value after the one we just inserted
                firstGreaterThan++;

                // Start again
                continue;
            }

            // If there's a gap between the lowest point in the range we're currently splitting and the current range, then split there
            if (firstGreaterThan->first.lower() < remaining.lower()) {
                // Split the ranges and move so that the lowest point matches
                firstGreaterThan = split(sets, firstGreaterThan->first, remaining.lower());
                firstGreaterThan++;
            }

            // If the current range ends beyond the end of the remaining set, then split it
            if (firstGreaterThan->first.upper() > remaining.upper()) {
                firstGreaterThan = split(sets, firstGreaterThan->first, remaining.upper());
            }

            // Current range should overlap the range specified by firstGreaterThan: add this identifier
            firstGreaterThan->second.insert(identifier);

            // Adjust the remaining set
            remaining = symbol_range(firstGreaterThan->first.upper(), remaining.upper());

            // Move on
            firstGreaterThan++;
        }
    }
}

/// \brief Factory method that generates a remapped symbol map by removing duplicates
///
/// This finds all the symbol sets that overlap in the original, and splits them up so that any given symbol is only in one set.
/// It sets up the remapping so it is possible to find the new set IDs for any symbol set in the original.
remapped_symbol_map* remapped_symbol_map::deduplicate(const symbol_map& source) {
    // Map of symbol ranges to the symbol sets in the original that contain them
    sets_for_range setsContainingRange;

    // Iterate through the sets in the source
    for (symbol_map::iterator symSet = source.begin(); symSet != source.end(); symSet++) {
        // Add this into the sets containing this range
        add_set(setsContainingRange, symSet->first, symSet->second);
    }

    // Create the result
    remapped_symbol_map* newSet = new remapped_symbol_map();

    // Create a new set for each range we got in the previous step
    for (sets_for_range::iterator it = setsContainingRange.begin(); it != setsContainingRange.end(); it++) {
        newSet->identifier_for_symbols(it->first, it->second);
    }

    // This is the result
    return newSet;
}
<|endoftext|>


<commit_before>#include "../../../../vowpalwabbit/parser.h"
#include "../../../../vowpalwabbit/vw.h"
#include "vw_VW.h"

void throw_java_exception(JNIEnv *env, const char* name, const char* msg) {
     jclass jc = env->FindClass(name);
     if (jc)
        env->ThrowNew (jc, msg);
}

void rethrow_cpp_exception_as_java_exception(JNIEnv *env) {
    try {
        throw;
    }
    catch(const std::bad_alloc& e) {
        throw_java_exception(env, "java/lang/OutOfMemoryError", e.what());
    }
    catch(const std::ios_base::failure& e) {
        throw_java_exception(env, "java/io/IOException", e.what());
    }
    catch(const std::exception& e) {
        const char* what = e.what();
        // It would appear that this text has changed between different boost variants
        std::string prefix1("unrecognised option");
        std::string prefix2("unknown option");

        std::cout << what << std::endl;

        if (std::string(what).substr(0, prefix1.size()) == prefix1 ||
            std::string(what).substr(0, prefix2.size()) == prefix2)
            throw_java_exception(env, "java/lang/IllegalArgumentException", what);
        else
            throw_java_exception(env, "java/lang/Exception", what);
    }
    catch (...) {
        throw_java_exception(env, "java/lang/Error", "Unidentified exception => "
                                   "rethrow_cpp_exception_as_java_exception "
                                   "may require some completion...");
    }
}

vw* getVW(jlong vwPtr) {
    return (vw*) vwPtr;
}

JNIEXPORT jlong JNICALL Java_vw_VW_initialize(JNIEnv *env, jobject obj, jstring command) {
    jlong vwPtr = 0;
    try {
        vwPtr = (jlong) VW::initialize(env->GetStringUTFChars(command, NULL));
    }
    catch(...) {
        rethrow_cpp_exception_as_java_exception(env);
    }
    return vwPtr;
}

JNIEXPORT jfloat JNICALL Java_vw_VW_predict(JNIEnv *env, jobject obj, jstring example_string, jboolean learn, jlong vwPtr) {
    float prediction = 0.0f;
    try {
        vw* vw = getVW(vwPtr);
        const char *utf_string = env->GetStringUTFChars(example_string, NULL);
        example *vec2 = VW::read_example(*vw, utf_string);
        if (learn)
            vw->l->learn(*vec2);
        else
            vw->l->predict(*vec2);
        if (vw->p->lp.parse_label == simple_label.parse_label)
            prediction = vec2->pred.scalar;
        else
            prediction = vec2->pred.multiclass;

        VW::finish_example(*vw, vec2);
        env->ReleaseStringUTFChars(example_string, utf_string);
        env->DeleteLocalRef(example_string);
    }
    catch (...) {
        rethrow_cpp_exception_as_java_exception(env);
    }
    return prediction;
}

JNIEXPORT jfloatArray JNICALL Java_vw_VW_batchPredict(JNIEnv *env, jobject obj, jobjectArray examples, jboolean learn, jlong vwPtr) {
    size_t len = env->GetArrayLength(examples);
    float* predictions = new float[len];
    for (size_t i=0; i<len; ++i) {
        jstring example = (jstring)env->GetObjectArrayElement(examples, i);
        predictions[i] = Java_vw_VW_predict(env, obj, example, learn, vwPtr);
        env->DeleteLocalRef(example);
    }
    jfloatArray jPredictions = env->NewFloatArray(len);
    env->SetFloatArrayRegion(jPredictions, 0, len, predictions);

    free(predictions);
    env->DeleteLocalRef(examples);
    return jPredictions;
}

JNIEXPORT void JNICALL Java_vw_VW_closeInstance(JNIEnv *env, jobject obj, jlong vwPtr) {
    try {
        VW::finish(*getVW(vwPtr));
    }
    catch(...) {
        rethrow_cpp_exception_as_java_exception(env);
    }
}
<commit_msg>Getting all Java tests to pass in Travis<commit_after>#include "../../../../vowpalwabbit/parser.h"
#include "../../../../vowpalwabbit/vw.h"
#include "vw_VW.h"

void throw_java_exception(JNIEnv *env, const char* name, const char* msg) {
     jclass jc = env->FindClass(name);
     if (jc)
        env->ThrowNew (jc, msg);
}

void rethrow_cpp_exception_as_java_exception(JNIEnv *env) {
    try {
        throw;
    }
    catch(const std::bad_alloc& e) {
        throw_java_exception(env, "java/lang/OutOfMemoryError", e.what());
    }
    catch(const std::ios_base::failure& e) {
        throw_java_exception(env, "java/io/IOException", e.what());
    }
    catch(const std::exception& e) {
        const char* what = e.what();
        std::string what_str = std::string(what);
        // It would appear that this text has changed between different boost variants
        std::string prefix1("unrecognised option");
        std::string prefix2("unknown option");

        std::cout << what_str << std::endl;
        std::cout << prefix2 << std::endl;
        std::cout << prefix2.size() << std::endl;
        std::cout << what_str.substr(0, prefix.size()) << std::endl;
        std::cout << what_str.substr(0, prefix2.size()) == prefix2 << std::endl;

        if (what_str.substr(0, prefix1.size()) == prefix1 ||
            what_str.substr(0, prefix2.size()) == prefix2)
            throw_java_exception(env, "java/lang/IllegalArgumentException", what);
        else
            throw_java_exception(env, "java/lang/Exception", what);
    }
    catch (...) {
        throw_java_exception(env, "java/lang/Error", "Unidentified exception => "
                                   "rethrow_cpp_exception_as_java_exception "
                                   "may require some completion...");
    }
}

vw* getVW(jlong vwPtr) {
    return (vw*) vwPtr;
}

JNIEXPORT jlong JNICALL Java_vw_VW_initialize(JNIEnv *env, jobject obj, jstring command) {
    jlong vwPtr = 0;
    try {
        vwPtr = (jlong) VW::initialize(env->GetStringUTFChars(command, NULL));
    }
    catch(...) {
        rethrow_cpp_exception_as_java_exception(env);
    }
    return vwPtr;
}

JNIEXPORT jfloat JNICALL Java_vw_VW_predict(JNIEnv *env, jobject obj, jstring example_string, jboolean learn, jlong vwPtr) {
    float prediction = 0.0f;
    try {
        vw* vw = getVW(vwPtr);
        const char *utf_string = env->GetStringUTFChars(example_string, NULL);
        example *vec2 = VW::read_example(*vw, utf_string);
        if (learn)
            vw->l->learn(*vec2);
        else
            vw->l->predict(*vec2);
        if (vw->p->lp.parse_label == simple_label.parse_label)
            prediction = vec2->pred.scalar;
        else
            prediction = vec2->pred.multiclass;

        VW::finish_example(*vw, vec2);
        env->ReleaseStringUTFChars(example_string, utf_string);
        env->DeleteLocalRef(example_string);
    }
    catch (...) {
        rethrow_cpp_exception_as_java_exception(env);
    }
    return prediction;
}

JNIEXPORT jfloatArray JNICALL Java_vw_VW_batchPredict(JNIEnv *env, jobject obj, jobjectArray examples, jboolean learn, jlong vwPtr) {
    size_t len = env->GetArrayLength(examples);
    float* predictions = new float[len];
    for (size_t i=0; i<len; ++i) {
        jstring example = (jstring)env->GetObjectArrayElement(examples, i);
        predictions[i] = Java_vw_VW_predict(env, obj, example, learn, vwPtr);
        env->DeleteLocalRef(example);
    }
    jfloatArray jPredictions = env->NewFloatArray(len);
    env->SetFloatArrayRegion(jPredictions, 0, len, predictions);

    free(predictions);
    env->DeleteLocalRef(examples);
    return jPredictions;
}

JNIEXPORT void JNICALL Java_vw_VW_closeInstance(JNIEnv *env, jobject obj, jlong vwPtr) {
    try {
        VW::finish(*getVW(vwPtr));
    }
    catch(...) {
        rethrow_cpp_exception_as_java_exception(env);
    }
}
<|endoftext|>


<commit_before>/**
 * @file pelleg_moore_kmeans_impl.hpp
 * @author Ryan Curtin
 *
 * An implementation of Pelleg-Moore's 'blacklist' algorithm for k-means
 * clustering.
 */
#ifndef __MLPACK_METHODS_KMEANS_PELLEG_MOORE_KMEANS_IMPL_HPP
#define __MLPACK_METHODS_KMEANS_PELLEG_MOORE_KMEANS_IMPL_HPP

#include "pelleg_moore_kmeans.hpp"
#include "pelleg_moore_kmeans_rules.hpp"

namespace mlpack {
namespace kmeans {

template<typename MetricType, typename MatType>
PellegMooreKMeans<MetricType, MatType>::PellegMooreKMeans(
    const MatType& dataset,
    MetricType& metric) :
    datasetOrig(dataset),
    dataset(tree::TreeTraits<TreeType>::RearrangesDataset ? datasetCopy :
        datasetOrig),
    metric(metric),
    distanceCalculations(0)
{
  Timer::Start("tree_building");

  // Copy the dataset, if necessary.
  if (tree::TreeTraits<TreeType>::RearrangesDataset)
    datasetCopy = datasetOrig;

  // Now build the tree.  We don't need any mappings.
  tree = new TreeType(const_cast<typename TreeType::Mat&>(this->dataset));

  Timer::Stop("tree_building");
}

template<typename MetricType, typename MatType>
PellegMooreKMeans<MetricType, MatType>::~PellegMooreKMeans()
{
  delete tree;
}

// Run a single iteration.
template<typename MetricType, typename MatType>
double PellegMooreKMeans<MetricType, MatType>::Iterate(
    const arma::mat& centroids,
    arma::mat& newCentroids,
    arma::Col<size_t>& counts)
{
  newCentroids.zeros(centroids.n_rows, centroids.n_cols);
  counts.zeros(centroids.n_cols);

  // Create rules object.
  typedef PellegMooreKMeansRules<MetricType, TreeType> RulesType;
  RulesType rules(dataset, centroids, newCentroids, counts, metric);

  // Use single-tree traverser.
  typename TreeType::template SingleTreeTraverser<RulesType> traverser(rules);

  // Now, do a traversal with a fake query index (since the query index is
  // irrelevant; we are checking each node with all clusters.
  traverser.Traverse(0, *tree);

  distanceCalculations += rules.DistanceCalculations();

  // Now, calculate how far the clusters moved, after normalizing them.
  double residual = 0.0;
  for (size_t c = 0; c < centroids.n_cols; ++c)
  {
    if (counts[c] == 0)
    {
      newCentroids.col(c).fill(DBL_MAX); // Should have happened anyway I think.
    }
    else
    {
      newCentroids.col(c) /= counts(c);
      residual += std::pow(metric.Evaluate(centroids.col(c),
                                           newCentroids.col(c)), 2.0);
    }
  }

  return std::sqrt(residual);
}

} // namespace kmeans
} // namespace mlpack

#endif
<commit_msg>I suppose we should exercise at least some caution in the destructor.<commit_after>/**
 * @file pelleg_moore_kmeans_impl.hpp
 * @author Ryan Curtin
 *
 * An implementation of Pelleg-Moore's 'blacklist' algorithm for k-means
 * clustering.
 */
#ifndef __MLPACK_METHODS_KMEANS_PELLEG_MOORE_KMEANS_IMPL_HPP
#define __MLPACK_METHODS_KMEANS_PELLEG_MOORE_KMEANS_IMPL_HPP

#include "pelleg_moore_kmeans.hpp"
#include "pelleg_moore_kmeans_rules.hpp"

namespace mlpack {
namespace kmeans {

template<typename MetricType, typename MatType>
PellegMooreKMeans<MetricType, MatType>::PellegMooreKMeans(
    const MatType& dataset,
    MetricType& metric) :
    datasetOrig(dataset),
    dataset(tree::TreeTraits<TreeType>::RearrangesDataset ? datasetCopy :
        datasetOrig),
    metric(metric),
    distanceCalculations(0)
{
  Timer::Start("tree_building");

  // Copy the dataset, if necessary.
  if (tree::TreeTraits<TreeType>::RearrangesDataset)
    datasetCopy = datasetOrig;

  // Now build the tree.  We don't need any mappings.
  tree = new TreeType(const_cast<typename TreeType::Mat&>(this->dataset));

  Timer::Stop("tree_building");
}

template<typename MetricType, typename MatType>
PellegMooreKMeans<MetricType, MatType>::~PellegMooreKMeans()
{
  if (tree)
    delete tree;
}

// Run a single iteration.
template<typename MetricType, typename MatType>
double PellegMooreKMeans<MetricType, MatType>::Iterate(
    const arma::mat& centroids,
    arma::mat& newCentroids,
    arma::Col<size_t>& counts)
{
  newCentroids.zeros(centroids.n_rows, centroids.n_cols);
  counts.zeros(centroids.n_cols);

  // Create rules object.
  typedef PellegMooreKMeansRules<MetricType, TreeType> RulesType;
  RulesType rules(dataset, centroids, newCentroids, counts, metric);

  // Use single-tree traverser.
  typename TreeType::template SingleTreeTraverser<RulesType> traverser(rules);

  // Now, do a traversal with a fake query index (since the query index is
  // irrelevant; we are checking each node with all clusters.
  traverser.Traverse(0, *tree);

  distanceCalculations += rules.DistanceCalculations();

  // Now, calculate how far the clusters moved, after normalizing them.
  double residual = 0.0;
  for (size_t c = 0; c < centroids.n_cols; ++c)
  {
    if (counts[c] == 0)
    {
      newCentroids.col(c).fill(DBL_MAX); // Should have happened anyway I think.
    }
    else
    {
      newCentroids.col(c) /= counts(c);
      residual += std::pow(metric.Evaluate(centroids.col(c),
                                           newCentroids.col(c)), 2.0);
    }
  }

  return std::sqrt(residual);
}

} // namespace kmeans
} // namespace mlpack

#endif
<|endoftext|>


<commit_before>#include <string>
#include <iostream>
#include <cstring>
#include <vector>
#include <utility>

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "dns.h"

/*
 * Decode
 */
void Dns::decode(const char* buffer)
{
    decode_hdr(buffer);
    buffer += hdr_offset;

    decode_qname(buffer);
    m_qType = get16bits(buffer);
    m_qClass = get16bits(buffer);
    //std::cout << "m_qName:" << m_qName << "\n";
    //std::cout << "m_qType:" << m_qType << "\n";
    //std::cout << "m_qClass:" << m_qClass << "\n";

    is_csubnet = false;
    if (dns_hdr.adcount)
        decode_additional(buffer);
}

void Dns::decode_hdr(const char* buffer)
{
    dns_hdr = *(struct dnshdr*) buffer;

	//dns_hdr.id = EXTRACT_16BITS(&dns_hdr.id);
	dns_hdr.qucount = EXTRACT_16BITS(&dns_hdr.qucount);
	//dns_hdr.ancount = EXTRACT_16BITS(&dns_hdr.ancount);
	//dns_hdr.aucount = EXTRACT_16BITS(&dns_hdr.aucount);
	dns_hdr.adcount = EXTRACT_16BITS(&dns_hdr.adcount);
}

void Dns::decode_qname(const char*& buffer)
{
    int i;
    char c;

    m_qName = "";

    int length = *buffer++;
    while (length != 0) {
        for (i = 0; i < length; i++) {
            c = *buffer++;
            m_qName += c;
        }
        length = *buffer++;
        if (length != 0) m_qName += '.';
    }

    query_len = m_qName.length() + 2 + 4;
}

void Dns::decode_additional(const char* buffer)
{
    opt = *(struct optrr*) buffer;
    opt.opt_type = EXTRACT_16BITS(&opt.opt_type);
    opt.opt_udpsize = EXTRACT_16BITS(&opt.opt_udpsize);
    opt.opt_ttl = EXTRACT_32BITS(&opt.opt_ttl);
    opt.rdlen = EXTRACT_16BITS(&opt.rdlen);
    /*std::cout << "name=" << (uint16_t) opt.opt_name
              << ", type=" << opt.opt_type
              << ", class=" << opt.opt_udpsize
              << ", ttl=" << opt.opt_ttl
              << ", rdlen=" << opt.rdlen << "\n";*/
    if (opt.rdlen)
        decode_option(buffer + 11);
}

void Dns::decode_option(const char* p)
{
    uint16_t tmp = *(uint16_t*) p;
    if (tmp == 0x0800) {
        is_csubnet = true;

        eo = *(struct edns0opt*) p;
        eo.opt_code = EXTRACT_16BITS(&eo.opt_code);
        eo.opt_len = EXTRACT_16BITS(&eo.opt_len);
        eo.family = EXTRACT_16BITS(&eo.family);
        inet_ntop(AF_INET, &eo.sub_addr, client_ip, 16);

        /*std::cout << "opt_code=" << eo.opt_code
                  << ", opt_len=" << eo.opt_len
                  << ", family=" << eo.family
                  << ", smask=" << (uint16_t)eo.source_netmask
                  << ", scropmask=" << (uint16_t)eo.scope_netmask
                  << ", client_ip=" << client_ip << "\n";*/
    } else if (tmp == 0x0a00) {
        co = *(struct cookieopt*) p;
        co.opt_code = EXTRACT_16BITS(&co.opt_code);
        co.opt_len = EXTRACT_16BITS(&co.opt_len);
    }
}

/*
 * Code
 */
int Dns::code(char* buffer)
{
    char* bufferBegin = buffer;
    char* start_hdr = buffer;
    uint32_t intip;

    domain_ip_len_ = domain_ip_.length();
    std::strncpy(cstr, domain_ip_.c_str(), domain_ip_len_);
    cstr[domain_ip_len_] = '\0';

    dns_hdr.ancount = 0;

    //code_hdr(buffer);
    //buffer += hdr_offset;

    /* Code Question section */
    buffer += hdr_offset + query_len;

    /* Code Answer section */
    m_ra.r_zone = 0xc00c;
    m_ra.r_ttl = 0;
    m_ra.r_size = 4;

    char* p = std::strtok(cstr, ",");
    while (p) {
		put16bits(buffer, m_ra.r_zone);
		put16bits(buffer, m_qType);
		put16bits(buffer, m_qClass);
		put32bits(buffer, m_ra.r_ttl);
		put16bits(buffer, m_ra.r_size);

        inet_pton(AF_INET, p, (void *)&intip);
        buffer[0] = (intip & 0xFF);
        buffer[1] = (intip & 0xFF00) >> 8;
        buffer[2] = (intip & 0xFF0000) >> 16;
        buffer[3] = (intip & 0xFF000000) >> 24;
        buffer += 4;

        dns_hdr.ancount++;
        if (dns_hdr.ancount >= 10) break;

        p = std::strtok(NULL, ",");
    }

    /* Code Additional section */
    if (dns_hdr.adcount) {
        buffer[0] = opt.opt_name;
        buffer++;
        put16bits(buffer, opt.opt_type);
        opt.opt_udpsize = 512;
        put16bits(buffer, opt.opt_udpsize);
        put32bits(buffer, opt.opt_ttl);

        if (opt.rdlen)
            opt.rdlen = 12;
        put16bits(buffer, opt.rdlen);

        if (opt.rdlen) {
            if (is_csubnet) {
                put16bits(buffer, eo.opt_code);
                put16bits(buffer, eo.opt_len);
                put16bits(buffer, eo.family);
                buffer[0] = eo.source_netmask;
                buffer[1] = eo.scope_netmask;
                buffer += 2;
                buffer[0] = (eo.sub_addr & 0xFF);
                buffer[1] = (eo.sub_addr & 0xFF00) >> 8;
                buffer[2] = (eo.sub_addr & 0xFF0000) >> 16;
                buffer[3] = (eo.sub_addr & 0xFF000000) >> 24;
                buffer += 4;
            } else {
                put16bits(buffer, co.opt_code);
                put16bits(buffer, co.opt_len);
                for (unsigned i = 0; i < 8; i++) {
                    buffer[i] = co.client_cookie[i];
                }
                buffer += 8;
            }
        }
    }

    code_hdr(start_hdr);

    return (buffer - bufferBegin);
}

void Dns::code_hdr(char*& buffer)
{
//	dns_hdr.flags1 = 0x81;
//	dns_hdr.flags2 = 0x80;
	dns_hdr.qucount	= 1;
	//dns_hdr.ancount	= 1;
//	dns_hdr.nscount	= 0;
//	dns_hdr.arcount	= 0;

	buffer += 2;  // skip id
	buffer[0] = 0x81;
	buffer[1] = 0x80;
	buffer += 2;  // skip flags
	put16bits(buffer, dns_hdr.qucount);
	put16bits(buffer, dns_hdr.ancount);
	//buffer += 4;  // skip auth and add
}

void Dns::code_domain(char*& buffer, const std::string& domain)
{
    int start(0); // indexes
    std::size_t end;

    while ((end = domain.find('.', start)) != std::string::npos) {
        *buffer++ = end - start; // label length octet
        for (unsigned i=start; i<end; i++) {
            *buffer++ = domain[i]; // label octets
        }
        start = end + 1; // Skip '.'
    }

    *buffer++ = domain.size() - start; // last label length octet
    for (unsigned i=start; i<domain.size(); i++) {
        *buffer++ = domain[i]; // last label octets
    }

    *buffer++ = 0;
}

<commit_msg>Added edns experimental option code<commit_after>#include <string>
#include <iostream>
#include <cstring>
#include <vector>
#include <utility>

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "dns.h"

/*
 * Decode
 */
void Dns::decode(const char* buffer)
{
    decode_hdr(buffer);
    buffer += hdr_offset;

    decode_qname(buffer);
    m_qType = get16bits(buffer);
    m_qClass = get16bits(buffer);
    //std::cout << "m_qName:" << m_qName << "\n";
    //std::cout << "m_qType:" << m_qType << "\n";
    //std::cout << "m_qClass:" << m_qClass << "\n";

    is_csubnet = false;
    if (dns_hdr.adcount)
        decode_additional(buffer);
}

void Dns::decode_hdr(const char* buffer)
{
    dns_hdr = *(struct dnshdr*) buffer;

	//dns_hdr.id = EXTRACT_16BITS(&dns_hdr.id);
	dns_hdr.qucount = EXTRACT_16BITS(&dns_hdr.qucount);
	//dns_hdr.ancount = EXTRACT_16BITS(&dns_hdr.ancount);
	//dns_hdr.aucount = EXTRACT_16BITS(&dns_hdr.aucount);
	dns_hdr.adcount = EXTRACT_16BITS(&dns_hdr.adcount);
}

void Dns::decode_qname(const char*& buffer)
{
    int i;
    char c;

    m_qName = "";

    int length = *buffer++;
    while (length != 0) {
        for (i = 0; i < length; i++) {
            c = *buffer++;
            m_qName += c;
        }
        length = *buffer++;
        if (length != 0) m_qName += '.';
    }

    query_len = m_qName.length() + 2 + 4;
}

void Dns::decode_additional(const char* buffer)
{
    opt = *(struct optrr*) buffer;
    opt.opt_type = EXTRACT_16BITS(&opt.opt_type);
    opt.opt_udpsize = EXTRACT_16BITS(&opt.opt_udpsize);
    opt.opt_ttl = EXTRACT_32BITS(&opt.opt_ttl);
    opt.rdlen = EXTRACT_16BITS(&opt.rdlen);
    /*std::cout << "name=" << (uint16_t) opt.opt_name
              << ", type=" << opt.opt_type
              << ", class=" << opt.opt_udpsize
              << ", ttl=" << opt.opt_ttl
              << ", rdlen=" << opt.rdlen << "\n";*/
    if (opt.rdlen)
        decode_option(buffer + 11);
}

void Dns::decode_option(const char* p)
{
    uint16_t tmp = *(uint16_t*) p;
    if (tmp == 0x0800 || tmp == 0xfa50) {
        is_csubnet = true;

        eo = *(struct edns0opt*) p;
        eo.opt_code = EXTRACT_16BITS(&eo.opt_code);
        eo.opt_len = EXTRACT_16BITS(&eo.opt_len);
        eo.family = EXTRACT_16BITS(&eo.family);
        inet_ntop(AF_INET, &eo.sub_addr, client_ip, 16);

        /*std::cout << "opt_code=" << eo.opt_code
                  << ", opt_len=" << eo.opt_len
                  << ", family=" << eo.family
                  << ", smask=" << (uint16_t)eo.source_netmask
                  << ", scropmask=" << (uint16_t)eo.scope_netmask
                  << ", client_ip=" << client_ip << "\n";*/
    } else if (tmp == 0x0a00) {
        co = *(struct cookieopt*) p;
        co.opt_code = EXTRACT_16BITS(&co.opt_code);
        co.opt_len = EXTRACT_16BITS(&co.opt_len);
    }
}

/*
 * Code
 */
int Dns::code(char* buffer)
{
    char* bufferBegin = buffer;
    char* start_hdr = buffer;
    uint32_t intip;

    domain_ip_len_ = domain_ip_.length();
    std::strncpy(cstr, domain_ip_.c_str(), domain_ip_len_);
    cstr[domain_ip_len_] = '\0';

    dns_hdr.ancount = 0;

    //code_hdr(buffer);
    //buffer += hdr_offset;

    /* Code Question section */
    buffer += hdr_offset + query_len;

    /* Code Answer section */
    m_ra.r_zone = 0xc00c;
    m_ra.r_ttl = 0;
    m_ra.r_size = 4;

    char* p = std::strtok(cstr, ",");
    while (p) {
		put16bits(buffer, m_ra.r_zone);
		put16bits(buffer, m_qType);
		put16bits(buffer, m_qClass);
		put32bits(buffer, m_ra.r_ttl);
		put16bits(buffer, m_ra.r_size);

        inet_pton(AF_INET, p, (void *)&intip);
        buffer[0] = (intip & 0xFF);
        buffer[1] = (intip & 0xFF00) >> 8;
        buffer[2] = (intip & 0xFF0000) >> 16;
        buffer[3] = (intip & 0xFF000000) >> 24;
        buffer += 4;

        dns_hdr.ancount++;
        if (dns_hdr.ancount >= 10) break;

        p = std::strtok(NULL, ",");
    }

    /* Code Additional section */
    if (dns_hdr.adcount) {
        buffer[0] = opt.opt_name;
        buffer++;
        put16bits(buffer, opt.opt_type);
        opt.opt_udpsize = 512;
        put16bits(buffer, opt.opt_udpsize);
        put32bits(buffer, opt.opt_ttl);

        if (opt.rdlen)
            opt.rdlen = 12;
        put16bits(buffer, opt.rdlen);

        if (opt.rdlen) {
            if (is_csubnet) {
                put16bits(buffer, eo.opt_code);
                put16bits(buffer, eo.opt_len);
                put16bits(buffer, eo.family);
                buffer[0] = eo.source_netmask;
                buffer[1] = eo.scope_netmask;
                buffer += 2;
                buffer[0] = (eo.sub_addr & 0xFF);
                buffer[1] = (eo.sub_addr & 0xFF00) >> 8;
                buffer[2] = (eo.sub_addr & 0xFF0000) >> 16;
                buffer[3] = (eo.sub_addr & 0xFF000000) >> 24;
                buffer += 4;
            } else {
                put16bits(buffer, co.opt_code);
                put16bits(buffer, co.opt_len);
                for (unsigned i = 0; i < 8; i++) {
                    buffer[i] = co.client_cookie[i];
                }
                buffer += 8;
            }
        }
    }

    code_hdr(start_hdr);

    return (buffer - bufferBegin);
}

void Dns::code_hdr(char*& buffer)
{
//	dns_hdr.flags1 = 0x81;
//	dns_hdr.flags2 = 0x80;
	dns_hdr.qucount	= 1;
	//dns_hdr.ancount	= 1;
//	dns_hdr.nscount	= 0;
//	dns_hdr.arcount	= 0;

	buffer += 2;  // skip id
	buffer[0] = 0x81;
	buffer[1] = 0x80;
	buffer += 2;  // skip flags
	put16bits(buffer, dns_hdr.qucount);
	put16bits(buffer, dns_hdr.ancount);
	//buffer += 4;  // skip auth and add
}

void Dns::code_domain(char*& buffer, const std::string& domain)
{
    int start(0); // indexes
    std::size_t end;

    while ((end = domain.find('.', start)) != std::string::npos) {
        *buffer++ = end - start; // label length octet
        for (unsigned i=start; i<end; i++) {
            *buffer++ = domain[i]; // label octets
        }
        start = end + 1; // Skip '.'
    }

    *buffer++ = domain.size() - start; // last label length octet
    for (unsigned i=start; i<domain.size(); i++) {
        *buffer++ = domain[i]; // last label octets
    }

    *buffer++ = 0;
}

<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2013-2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <print.hpp>
#include <system.hpp>
#include <string.hpp>

int main(){
    char input_buffer[64];

    while(true){
        print("thor> ");

        auto c = read_input(input_buffer, 63);

        if(input_buffer[c-1] == '\n'){
            if(c == 1){
                print_line();
                continue;
            }

            input_buffer[c-1] = '\0';

            if(str_equals(input_buffer, "exit")){
                exit(0);
            } else if(str_equals(input_buffer, "long")){
                //TODO Remove this function when exec system is complete
                exec_and_wait("long");
            } else if(str_equals(input_buffer, "sleep")){
                //TODO Once better infrastrucure, parse command line and sleep the
                //correct number of milliseconds
                sleep_ms(5000);
            } else {
                print_line("Unknown command");
            }
        } else {
            //TODO Once in good shape, just append to current input buffer
        }

    }
}<commit_msg>Clean<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2013-2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <print.hpp>
#include <system.hpp>
#include <string.hpp>

int main(){
    char input_buffer[64];

    while(true){
        print("thor> ");

        auto c = read_input(input_buffer, 63);

        if(input_buffer[c-1] == '\n'){
            if(c == 1){
                print_line();
                continue;
            }

            input_buffer[c-1] = '\0';

            if(str_equals(input_buffer, "exit")){
                exit(0);
            } else if(str_equals(input_buffer, "long")){
                //TODO Remove this function when exec system is complete
                exec_and_wait("long");
            } else if(str_equals(input_buffer, "sleep")){
                //TODO Once better infrastrucure, parse command line and sleep the
                //correct number of milliseconds
                sleep_ms(5000);
            } else {
                print_line("Unknown command");
            }
        } else {
            //TODO Once in good shape, just append to current input buffer
        }
    }
}<|endoftext|>


<commit_before>/*
    Persons Model Item
    Represents one person in the model
    Copyright (C) 2012  Martin Klapetek <martin.klapetek@gmail.com>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "persons-model-item.h"
#include "persons-model-contact-item.h"

#include <Nepomuk/Vocabulary/PIMO>
#include <Nepomuk/Vocabulary/NCO>
#include <Soprano/Vocabulary/NAO>

PersonsModelItem::PersonsModelItem(const QUrl &personUri)
{
    setData(personUri, PersonsModel::UriRole);
}

QVariant PersonsModelItem::queryChildrenForRole(int role) const
{
    for (int i = 0; i < rowCount(); i++) {
        QVariant value = child(i)->data(role);
        if (!value.isNull()) {
            return value;
        }
    }
    return QVariant();
}

QVariantList PersonsModelItem::queryChildrenForRoleList(int role) const
{
    QVariantList ret;
    for (int i = 0; i < rowCount(); i++) {
        QVariant value = child(i)->data(role);
        if (!value.isNull()) {
            ret += value;
        }
    }
    return ret;
}

QVariant PersonsModelItem::data(int role) const
{
    switch(role) {
        case PersonsModel::NameRole:
        case Qt::DisplayRole: {
            QVariant value = queryChildrenForRole(Qt::DisplayRole);
            if(value.isNull())
                return QString("PIMO:Person - %1").arg(data(PersonsModel::UriRole).toString());
            else
                return value;
        }
        case PersonsModel::NickRole:
            return queryChildrenForRole(role);
        case PersonsModel::IMRole:
        case PersonsModel::PhoneRole:
        case PersonsModel::EmailRole:
        case PersonsModel::PhotoRole:
            return queryChildrenForRoleList(role);
    }

    return QStandardItem::data(role);
}
<commit_msg>Make it possible to provide all person's contact id's<commit_after>/*
    Persons Model Item
    Represents one person in the model
    Copyright (C) 2012  Martin Klapetek <martin.klapetek@gmail.com>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "persons-model-item.h"
#include "persons-model-contact-item.h"

#include <Nepomuk/Vocabulary/PIMO>
#include <Nepomuk/Vocabulary/NCO>
#include <Soprano/Vocabulary/NAO>

PersonsModelItem::PersonsModelItem(const QUrl &personUri)
{
    setData(personUri, PersonsModel::UriRole);
}

QVariant PersonsModelItem::queryChildrenForRole(int role) const
{
    for (int i = 0; i < rowCount(); i++) {
        QVariant value = child(i)->data(role);
        if (!value.isNull()) {
            return value;
        }
    }
    return QVariant();
}

QVariantList PersonsModelItem::queryChildrenForRoleList(int role) const
{
    QVariantList ret;
    for (int i = 0; i < rowCount(); i++) {
        QVariant value = child(i)->data(role);
        if (!value.isNull()) {
            ret += value;
        }
    }
    return ret;
}

QVariant PersonsModelItem::data(int role) const
{
    switch(role) {
        case PersonsModel::NameRole:
        case Qt::DisplayRole: {
            QVariant value = queryChildrenForRole(Qt::DisplayRole);
            if(value.isNull())
                return QString("PIMO:Person - %1").arg(data(PersonsModel::UriRole).toString());
            else
                return value;
        }
        case PersonsModel::NickRole:
            return queryChildrenForRole(role);
        case PersonsModel::IMRole:
        case PersonsModel::PhoneRole:
        case PersonsModel::EmailRole:
        case PersonsModel::PhotoRole:
        case PersonsModel::ContactIdRole:
            return queryChildrenForRoleList(role);
    }

    return QStandardItem::data(role);
}
<|endoftext|>


<commit_before>#include <istream>
#include <ostream>
#include <algorithm>
#include <stdexcept>
#include <iterator>
#include <utility>

#include <boost/property_tree/json_parser.hpp>
#include <boost/range/algorithm/sort.hpp>
#include <boost/range/algorithm/unique.hpp>
#include <boost/range/algorithm_ext/erase.hpp>
#include <boost/regex.hpp>

#include "parser.h"

namespace claudia {

/*
 * multiline support missing in most environments; parse line-by-line
 * see: http://cplusplus.github.io/LWG/lwg-active.html#2343
 */
parser::parser(std::istream& in, const std::string& format)
{
  std::vector<std::string> lines;

  for (std::string line; std::getline(in, line);)
    lines.emplace_back(std::move(line));

  const boost::regex pattern{format, boost::regex::optimize};
  boost::smatch match;

  auto it = std::make_move_iterator(std::begin(lines));
  auto end = std::make_move_iterator(std::end(lines));

  /* exception safe parsing */
  decltype(diagnostics_) local;

  /* non-matches are silently ignored */
  std::for_each(it, end, [&](std::string line) {
    if (boost::regex_search(std::move(line), match, pattern))
      local.emplace_back(match[1], std::stoull(match[2]), std::stoull(match[3]), match[4], match[5]);
  });

  /* no std::set -- this way it's more memory friendly */
  boost::erase(local, boost::unique<boost::return_found_end>(boost::sort(local)));

  diagnostics_ = std::move(local);
}

void parser::report(std::ostream& out, bool summary) const
{
  boost::property_tree::ptree root;

  if (summary)
    root.add_child("summary", do_summary());

  root.add_child("diagnostics", do_report());

  boost::property_tree::write_json(out, root);
}

boost::property_tree::ptree parser::do_summary() const
{
  boost::property_tree::ptree root;

  // XXX: statistics
  // root.put(k, v);

  return root;
}

boost::property_tree::ptree parser::do_report() const
{
  boost::property_tree::ptree root;

  for (const auto diagnostic : diagnostics_)
    root.push_back(std::make_pair("", diagnostic.report()));

  return root;
}
}
<commit_msg>Detect user-provided format mismatch on sub-match extraction<commit_after>#include <istream>
#include <ostream>
#include <algorithm>
#include <stdexcept>
#include <iterator>
#include <utility>

#include <boost/property_tree/json_parser.hpp>
#include <boost/range/algorithm/sort.hpp>
#include <boost/range/algorithm/unique.hpp>
#include <boost/range/algorithm_ext/erase.hpp>
#include <boost/regex.hpp>

#include "parser.h"

namespace claudia {

/*
 * multiline support missing in most environments; parse line-by-line
 * see: http://cplusplus.github.io/LWG/lwg-active.html#2343
 */
parser::parser(std::istream& in, const std::string& format)
{
  std::vector<std::string> lines;

  for (std::string line; std::getline(in, line);)
    lines.emplace_back(std::move(line));

  const boost::regex pattern{format, boost::regex::optimize};
  boost::smatch match;

  auto it = std::make_move_iterator(std::begin(lines));
  auto end = std::make_move_iterator(std::end(lines));

  /* exception safe parsing */
  decltype(diagnostics_) local;

  /* non-matches are silently ignored */
  std::for_each(it, end, [&](std::string line) {
    if (boost::regex_search(std::move(line), match, pattern)) {
      /* 0th sub-match is entire matched expression */
      if (match.size() - 1 != 5)
        throw std::runtime_error{"bad format: five groups required: file, line, column, message, flag"};

      local.emplace_back(match[1], std::stoull(match[2]), std::stoull(match[3]), match[4], match[5]);
    }
  });

  /* no std::set -- this way it's more memory friendly */
  boost::erase(local, boost::unique<boost::return_found_end>(boost::sort(local)));

  diagnostics_ = std::move(local);
}

void parser::report(std::ostream& out, bool summary) const
{
  boost::property_tree::ptree root;

  if (summary)
    root.add_child("summary", do_summary());

  root.add_child("diagnostics", do_report());

  boost::property_tree::write_json(out, root);
}

boost::property_tree::ptree parser::do_summary() const
{
  boost::property_tree::ptree root;

  // XXX: statistics
  // root.put(k, v);

  return root;
}

boost::property_tree::ptree parser::do_report() const
{
  boost::property_tree::ptree root;

  for (const auto diagnostic : diagnostics_)
    root.push_back(std::make_pair("", diagnostic.report()));

  return root;
}
}
<|endoftext|>


<commit_before>/*
 * fPls - playlist handler for fIcy
 * Copyright(c) 2004-2008 of wave++ (Yuri D'Elia) <wavexx@thregr.org>
 * Distributed under GNU LGPL without ANY warranty.
 */

// local headers
#include "fIcy.hh"
#include "msg.hh"
#include "htfollow.hh"
#include "plsparse.hh"
#include "tmparse.hh"
#include "authparse.hh"
using std::string;
using std::list;
using std::map;

// system headers
#include <fstream>
using std::ifstream;

#include <sstream>
using std::istringstream;

#include <iostream>
using std::cout;

#include <memory>
using std::auto_ptr;

#include <stdexcept>
using std::runtime_error;

// c system headers
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <time.h>
#include <errno.h>
#include <fcntl.h>

/*
 * Parameters handling
 */
class Params
{
public:
  explicit
  Params(int argc, char* argv[]);

  ~Params() throw()
  {
    if(fIcyParams)
      delete[] fIcyParams;
  }

  const char* uri;
  const char** fIcyParams;
  size_t urlPos;
  size_t timePos;
  size_t maxRetries;
  long maxLoops;
  time_t waitSecs;
  time_t maxTime;
  time_t idleTime;
  size_t maxFollow;
  char* daemonize;
  char* auth;
  Http::Auth authData;
  bool help;
};

Params::Params(int argc, char* argv[])
{
  // defaults
  prg = argv[0];
  maxRetries = fIcy::maxRetries;
  maxLoops = fIcy::maxLoops;
  waitSecs = fIcy::waitSecs;
  maxTime = 0;
  maxFollow = fIcy::maxFollow;
  idleTime = 0;
  verbose = help = false;
  daemonize = NULL;
  auth = NULL;

  // locals
  const char* path = "fIcy";
  const char* maxFollowBuf = NULL;
  const char* idleTimeBuf = NULL;
  int arg;

  // let's again put a bit of SHAME... those FSC**BEEP GNU extensions.
  // WHY _NOT_ BEING POSIXLY_CORRECT BY DEFAULT EH? oooh, "features"! I see.
  while((arg = getopt(argc, argv, "+P:R:L:T:M:l:d:a:vhi:")) != -1)
    switch(arg)
    {
    case 'P':
      path = optarg;
      break;

    case 'R':
      maxRetries = strtoul(optarg, NULL, 0);
      break;

    case 'L':
      maxLoops = strtol(optarg, NULL, 0);
      break;

    case 'T':
      waitSecs = tmParse(optarg);
      break;

    case 'M':
      maxTime = tmParse(optarg);
      break;

    case 'l':
      maxFollowBuf = optarg;
      maxFollow = strtol(optarg, NULL, 0);
      break;

    case 'd':
      daemonize = optarg;
      break;

    case 'h':
      help = true;
      break;

    case 'a':
      auth = optarg;
      break;

    case 'v':
      verbose = true;
      break;

    case 'i':
      idleTimeBuf = optarg;
      idleTime = tmParse(optarg);
      break;
    }

  // fetch authentication tokens immediately to avoid further requests
  if(auth)
    authParse(authData, auth);

  // playlist
  argc -= optind;
  uri = argv[optind++];

  // fIcy parameters
  if(--argc >= 0)
  {
    fIcyParams = new const char*[argc + 13];
    fIcyParams[0] = path;
    arg = 1;

    // parameters we allow to override
    if(auth)
    {
      fIcyParams[arg++] = "-a";
      fIcyParams[arg++] = auth;
    }
    if(maxFollowBuf)
    {
      fIcyParams[arg++] = "-l";
      fIcyParams[arg++] = maxFollowBuf;
    }
    if(idleTimeBuf)
    {
      fIcyParams[arg++] = "-i";
      fIcyParams[arg++] = idleTimeBuf;
    }

    // forward other parameters
    for(int i = 1; i <= argc; ++i)
      fIcyParams[arg++] = argv[optind++];

    // imposed parameters
    fIcyParams[arg++] = "-M";
    timePos = arg++;

    if(daemonize)
      fIcyParams[arg++] = "-d";

    fIcyParams[arg++] = "--";
    urlPos = arg++;

    fIcyParams[arg++] = NULL;
  }
  else
    fIcyParams = NULL;
}

void
show_help()
{
  cout << prg << fIcy::fPlsHelp << prg << " v" << fIcy::version <<
    " is\n" << fIcy::copyright;
}

void
load_file(string& out, const char* file)
{
  ifstream in(file);
  if(!in)
    throw runtime_error(string("cannot open ") + file);

  // load the file
  char buf[fIcy::bufSz];

  do
  {
    in.read(buf, sizeof(buf));
    out.append(buf, in.gcount());
  }
  while(in);

  if(!in.eof())
    throw runtime_error(string("errors while reading from ") + file);
}

void
load_url(string& out, const URL& url, const Params& params)
{
  // setup headers
  Http::Header qHeaders;
  qHeaders.push_back(fIcy::userAgent);
  if(params.auth)
    qHeaders.push_back(params.authData.basicHeader());

  // connection
  map<string, string> pReply;
  auto_ptr<Socket> s(htFollow(pReply, url, qHeaders,
	  params.maxFollow, params.idleTime,
	  params.maxRetries, params.waitSecs));

  // load the file
  char buf[fIcy::bufSz];
  size_t ret;

  while((ret = s->read(buf, sizeof(buf))) > 0)
    out.append(buf, ret);
}

void
load_list(string& buf, const char* uri, const Params& params)
{
  URL url(uri);

  if(url.proto == Http::Proto::proto)
    load_url(buf, url, params);
  else if(!url.proto.size())
  {
    msg("loading playlist from %s", uri);
    load_file(buf, uri);
  }
  else
    throw runtime_error(string("unknown protocol ") + url.proto);
}

// exec fIcy and return the exit code
int
exec_fIcy(Params& params, const time_t maxTime, const char* stream)
{
  const char** args = params.fIcyParams;
  char buf[16];
  snprintf(buf, sizeof(buf), "%lu", maxTime);
  args[params.timePos] = buf;
  args[params.urlPos] = stream;
  int ret;

  switch(fork())
  {
  case -1:
    err("cannot fork");
    return Exit::args;

  case 0:
    execvp(args[0], const_cast<char**>(args));
    err("cannot exec fIcy: %s", strerror(errno));
    exit(Exit::args);
  }

  wait(&ret);
  return (WIFEXITED(ret)? WEXITSTATUS(ret): Exit::args);
}

void
daemonize(const char* logFile)
{
  int fd;

  // ensure correctness before daemonization
  if(logFile)
    if((fd = open(logFile, O_WRONLY | O_APPEND | O_CREAT, 0666)) == -1)
      throw runtime_error((string("cannot open log file ") + logFile).c_str());

  // daemonize
#ifdef __sgi
  if(_daemonize(0, fd, -1, -1) == -1)
#else
  if(daemon(0, 0) == -1)
#endif
    throw runtime_error("cannot daemonize process");

  // fix stderr
  if(logFile)
    dup2(fd, STDERR_FILENO);
}

int
main(int argc, char* argv[]) try
{
  // initialize
  Params params(argc, argv);
  if(!params.uri && !params.help)
  {
    err("bad parameters; see %s -h", prg);
    return Exit::args;
  }
  if(params.help)
  {
    show_help();
    return Exit::args;
  }

  time_t start(time(NULL));
  time_t resTime(params.maxTime);

  // fetch and parse the playlist
  list<string> playlist;
  {
    string buf;
    load_list(buf, params.uri, params);
    istringstream stream(buf);
    plsParse(playlist, stream);
  }
  msg("loaded %d elements", playlist.size());

  // daemonize now if requested
  if(params.daemonize)
    daemonize(params.daemonize);

  // main loop
  for(size_t loop = 0; static_cast<long>(loop) != params.maxLoops; ++loop)
  {
    for(list<string>::const_iterator it = playlist.begin();
	it != playlist.end(); ++it)
    {
      for(size_t retry = 0; retry != params.maxRetries; ++retry)
      {
	// sweet dreams on temporary failures
	if(loop || it != playlist.begin())
	  sleep(params.waitSecs);

	// residual playing time
	if(params.maxTime)
	{
	  time_t d(time(NULL) - start);
	  if(d >= params.maxTime)
	    return Exit::success;
	  resTime = params.maxTime - d;
	}

	msg("stream %s: retry %d of loop %d", it->c_str(), retry + 1, loop + 1);

	int ret = exec_fIcy(params, resTime, it->c_str());
	if(ret == Exit::args)
	  return Exit::fail;

	// check for success after maxTime
	if(ret == Exit::success)
	  break;
      }
    }
  }

  return Exit::success;
}
catch(runtime_error& err)
{
  ::err("%s", err.what());
  return Exit::fail;
}
catch(...)
{
  err("unknown error, aborting");
  abort();
}
<commit_msg>fPls: sleep the defined amount when retrying.<commit_after>/*
 * fPls - playlist handler for fIcy
 * Copyright(c) 2004-2008 of wave++ (Yuri D'Elia) <wavexx@thregr.org>
 * Distributed under GNU LGPL without ANY warranty.
 */

// local headers
#include "fIcy.hh"
#include "msg.hh"
#include "htfollow.hh"
#include "plsparse.hh"
#include "tmparse.hh"
#include "authparse.hh"
using std::string;
using std::list;
using std::map;

// system headers
#include <fstream>
using std::ifstream;

#include <sstream>
using std::istringstream;

#include <iostream>
using std::cout;

#include <memory>
using std::auto_ptr;

#include <stdexcept>
using std::runtime_error;

// c system headers
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <time.h>
#include <errno.h>
#include <fcntl.h>

/*
 * Parameters handling
 */
class Params
{
public:
  explicit
  Params(int argc, char* argv[]);

  ~Params() throw()
  {
    if(fIcyParams)
      delete[] fIcyParams;
  }

  const char* uri;
  const char** fIcyParams;
  size_t urlPos;
  size_t timePos;
  size_t maxRetries;
  long maxLoops;
  time_t waitSecs;
  time_t maxTime;
  time_t idleTime;
  size_t maxFollow;
  char* daemonize;
  char* auth;
  Http::Auth authData;
  bool help;
};

Params::Params(int argc, char* argv[])
{
  // defaults
  prg = argv[0];
  maxRetries = fIcy::maxRetries;
  maxLoops = fIcy::maxLoops;
  waitSecs = fIcy::waitSecs;
  maxTime = 0;
  maxFollow = fIcy::maxFollow;
  idleTime = 0;
  verbose = help = false;
  daemonize = NULL;
  auth = NULL;

  // locals
  const char* path = "fIcy";
  const char* maxFollowBuf = NULL;
  const char* idleTimeBuf = NULL;
  int arg;

  // let's again put a bit of SHAME... those FSC**BEEP GNU extensions.
  // WHY _NOT_ BEING POSIXLY_CORRECT BY DEFAULT EH? oooh, "features"! I see.
  while((arg = getopt(argc, argv, "+P:R:L:T:M:l:d:a:vhi:")) != -1)
    switch(arg)
    {
    case 'P':
      path = optarg;
      break;

    case 'R':
      maxRetries = strtoul(optarg, NULL, 0);
      break;

    case 'L':
      maxLoops = strtol(optarg, NULL, 0);
      break;

    case 'T':
      waitSecs = tmParse(optarg);
      break;

    case 'M':
      maxTime = tmParse(optarg);
      break;

    case 'l':
      maxFollowBuf = optarg;
      maxFollow = strtol(optarg, NULL, 0);
      break;

    case 'd':
      daemonize = optarg;
      break;

    case 'h':
      help = true;
      break;

    case 'a':
      auth = optarg;
      break;

    case 'v':
      verbose = true;
      break;

    case 'i':
      idleTimeBuf = optarg;
      idleTime = tmParse(optarg);
      break;
    }

  // fetch authentication tokens immediately to avoid further requests
  if(auth)
    authParse(authData, auth);

  // playlist
  argc -= optind;
  uri = argv[optind++];

  // fIcy parameters
  if(--argc >= 0)
  {
    fIcyParams = new const char*[argc + 13];
    fIcyParams[0] = path;
    arg = 1;

    // parameters we allow to override
    if(auth)
    {
      fIcyParams[arg++] = "-a";
      fIcyParams[arg++] = auth;
    }
    if(maxFollowBuf)
    {
      fIcyParams[arg++] = "-l";
      fIcyParams[arg++] = maxFollowBuf;
    }
    if(idleTimeBuf)
    {
      fIcyParams[arg++] = "-i";
      fIcyParams[arg++] = idleTimeBuf;
    }

    // forward other parameters
    for(int i = 1; i <= argc; ++i)
      fIcyParams[arg++] = argv[optind++];

    // imposed parameters
    fIcyParams[arg++] = "-M";
    timePos = arg++;

    if(daemonize)
      fIcyParams[arg++] = "-d";

    fIcyParams[arg++] = "--";
    urlPos = arg++;

    fIcyParams[arg++] = NULL;
  }
  else
    fIcyParams = NULL;
}

void
show_help()
{
  cout << prg << fIcy::fPlsHelp << prg << " v" << fIcy::version <<
    " is\n" << fIcy::copyright;
}

void
load_file(string& out, const char* file)
{
  ifstream in(file);
  if(!in)
    throw runtime_error(string("cannot open ") + file);

  // load the file
  char buf[fIcy::bufSz];

  do
  {
    in.read(buf, sizeof(buf));
    out.append(buf, in.gcount());
  }
  while(in);

  if(!in.eof())
    throw runtime_error(string("errors while reading from ") + file);
}

void
load_url(string& out, const URL& url, const Params& params)
{
  // setup headers
  Http::Header qHeaders;
  qHeaders.push_back(fIcy::userAgent);
  if(params.auth)
    qHeaders.push_back(params.authData.basicHeader());

  // connection
  map<string, string> pReply;
  auto_ptr<Socket> s(htFollow(pReply, url, qHeaders,
	  params.maxFollow, params.idleTime,
	  params.maxRetries, params.waitSecs));

  // load the file
  char buf[fIcy::bufSz];
  size_t ret;

  while((ret = s->read(buf, sizeof(buf))) > 0)
    out.append(buf, ret);
}

void
load_list(string& buf, const char* uri, const Params& params)
{
  URL url(uri);

  if(url.proto == Http::Proto::proto)
    load_url(buf, url, params);
  else if(!url.proto.size())
  {
    msg("loading playlist from %s", uri);
    load_file(buf, uri);
  }
  else
    throw runtime_error(string("unknown protocol ") + url.proto);
}

// exec fIcy and return the exit code
int
exec_fIcy(Params& params, const time_t maxTime, const char* stream)
{
  const char** args = params.fIcyParams;
  char buf[16];
  snprintf(buf, sizeof(buf), "%lu", maxTime);
  args[params.timePos] = buf;
  args[params.urlPos] = stream;
  int ret;

  switch(fork())
  {
  case -1:
    err("cannot fork");
    return Exit::args;

  case 0:
    execvp(args[0], const_cast<char**>(args));
    err("cannot exec fIcy: %s", strerror(errno));
    exit(Exit::args);
  }

  wait(&ret);
  return (WIFEXITED(ret)? WEXITSTATUS(ret): Exit::args);
}

void
daemonize(const char* logFile)
{
  int fd;

  // ensure correctness before daemonization
  if(logFile)
    if((fd = open(logFile, O_WRONLY | O_APPEND | O_CREAT, 0666)) == -1)
      throw runtime_error((string("cannot open log file ") + logFile).c_str());

  // daemonize
#ifdef __sgi
  if(_daemonize(0, fd, -1, -1) == -1)
#else
  if(daemon(0, 0) == -1)
#endif
    throw runtime_error("cannot daemonize process");

  // fix stderr
  if(logFile)
    dup2(fd, STDERR_FILENO);
}

int
main(int argc, char* argv[]) try
{
  // initialize
  Params params(argc, argv);
  if(!params.uri && !params.help)
  {
    err("bad parameters; see %s -h", prg);
    return Exit::args;
  }
  if(params.help)
  {
    show_help();
    return Exit::args;
  }

  time_t start(time(NULL));
  time_t resTime(params.maxTime);

  // fetch and parse the playlist
  list<string> playlist;
  {
    string buf;
    load_list(buf, params.uri, params);
    istringstream stream(buf);
    plsParse(playlist, stream);
  }
  msg("loaded %d elements", playlist.size());

  // daemonize now if requested
  if(params.daemonize)
    daemonize(params.daemonize);

  // main loop
  for(size_t loop = 0; static_cast<long>(loop) != params.maxLoops; ++loop)
  {
    for(list<string>::const_iterator it = playlist.begin();
	it != playlist.end(); ++it)
    {
      for(size_t retry = 0; retry != params.maxRetries; ++retry)
      {
	// sweet dreams on temporary failures
	if(loop || retry || it != playlist.begin())
	  sleep(params.waitSecs);

	// residual playing time
	if(params.maxTime)
	{
	  time_t d(time(NULL) - start);
	  if(d >= params.maxTime)
	    return Exit::success;
	  resTime = params.maxTime - d;
	}

	msg("stream %s: retry %d of loop %d", it->c_str(), retry + 1, loop + 1);

	int ret = exec_fIcy(params, resTime, it->c_str());
	if(ret == Exit::args)
	  return Exit::fail;

	// check for success after maxTime
	if(ret == Exit::success)
	  break;
      }
    }
  }

  return Exit::success;
}
catch(runtime_error& err)
{
  ::err("%s", err.what());
  return Exit::fail;
}
catch(...)
{
  err("unknown error, aborting");
  abort();
}
<|endoftext|>


<commit_before>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2010, 2011, 2012, 2013, 2014, 2015
Raffaello D. Di Napoli

This file is part of Abaclade.

Abaclade is free software: you can redistribute it and/or modify it under the terms of the GNU
General Public License as published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

Abaclade 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 General
Public License for more details.

You should have received a copy of the GNU General Public License along with Abaclade. If not, see
<http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------------------------*/

#include <abaclade.hxx>
#ifdef _ABACLADE_STL_MEMORY_HXX

////////////////////////////////////////////////////////////////////////////////////////////////////

namespace abc { namespace _std {

bad_weak_ptr::bad_weak_ptr() {
}

/*virtual*/ bad_weak_ptr::~bad_weak_ptr() {
}

/*virtual*/ char const * bad_weak_ptr::what() const /*override*/ {
   return "abc::_std::bad_weak_ptr";
}

}} //namespace abc::_std

////////////////////////////////////////////////////////////////////////////////////////////////////

namespace abc { namespace _std { namespace detail {

shared_refcount::shared_refcount(unsigned cStrongRefs, unsigned cWeakRefs) :
   m_cStrongRefs(cStrongRefs),
   m_cWeakRefs(cWeakRefs + (cStrongRefs > 0 ? 1 : 0)) {
}

/*virtual*/ shared_refcount::~shared_refcount() {
   ABC_ASSERT(m_cStrongRefs == 0);
   ABC_ASSERT(m_cWeakRefs == 0);
}

void shared_refcount::add_strong_ref() {
   // Increment the count of strong references if non-zero; it it’s zero, the owned object is gone.
   unsigned cStrongRefsOld;
   do {
      cStrongRefsOld = m_cStrongRefs;
      if (cStrongRefsOld == 0) {
         throw bad_weak_ptr();
      }
   } while (!m_cStrongRefs.compare_exchange_strong(cStrongRefsOld, cStrongRefsOld + 1));
}

/*virtual*/ void * shared_refcount::get_deleter(type_info const & ti) const {
   ABC_UNUSED_ARG(ti);
   return nullptr;
}

/*virtual*/ void shared_refcount::delete_this() {
   delete this;
}

}}} //namespace abc::_std::detail

////////////////////////////////////////////////////////////////////////////////////////////////////

#endif //ifdef _ABACLADE_STL_MEMORY_HXX
<commit_msg>Fix use of atomics in abc::_std::detail::shared_refcount<commit_after>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2010, 2011, 2012, 2013, 2014, 2015
Raffaello D. Di Napoli

This file is part of Abaclade.

Abaclade is free software: you can redistribute it and/or modify it under the terms of the GNU
General Public License as published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

Abaclade 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 General
Public License for more details.

You should have received a copy of the GNU General Public License along with Abaclade. If not, see
<http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------------------------*/

#include <abaclade.hxx>
#ifdef _ABACLADE_STL_MEMORY_HXX

////////////////////////////////////////////////////////////////////////////////////////////////////

namespace abc { namespace _std {

bad_weak_ptr::bad_weak_ptr() {
}

/*virtual*/ bad_weak_ptr::~bad_weak_ptr() {
}

/*virtual*/ char const * bad_weak_ptr::what() const /*override*/ {
   return "abc::_std::bad_weak_ptr";
}

}} //namespace abc::_std

////////////////////////////////////////////////////////////////////////////////////////////////////

namespace abc { namespace _std { namespace detail {

shared_refcount::shared_refcount(unsigned cStrongRefs, unsigned cWeakRefs) :
   m_cStrongRefs(cStrongRefs),
   m_cWeakRefs(cWeakRefs + (cStrongRefs > 0 ? 1 : 0)) {
}

/*virtual*/ shared_refcount::~shared_refcount() {
   ABC_ASSERT(
      m_cStrongRefs.load() == 0,
      ABC_SL("shared_refcount being destructed with non-zero strong references!")
   );
   ABC_ASSERT(
      m_cWeakRefs.load() == 0,
      ABC_SL("shared_refcount being destructed with non-zero weak references!")
   );
}

void shared_refcount::add_strong_ref() {
   // Increment the count of strong references if non-zero; it it’s zero, the owned object is gone.
   unsigned cStrongRefsOld;
   do {
      cStrongRefsOld = m_cStrongRefs.load();
      if (cStrongRefsOld == 0) {
         throw bad_weak_ptr();
      }
   } while (!m_cStrongRefs.compare_exchange_strong(cStrongRefsOld, cStrongRefsOld + 1));
}

/*virtual*/ void * shared_refcount::get_deleter(type_info const & ti) const {
   ABC_UNUSED_ARG(ti);
   return nullptr;
}

/*virtual*/ void shared_refcount::delete_this() {
   delete this;
}

}}} //namespace abc::_std::detail

////////////////////////////////////////////////////////////////////////////////////////////////////

#endif //ifdef _ABACLADE_STL_MEMORY_HXX
<|endoftext|>