<commit_before>/* Copyright 2015 Realm Inc - All Rights Reserved
 * Proprietary and Confidential
 */

#import "js_results.hpp"
#import "js_object.hpp"
#import "object_accessor.hpp"
#import "results.hpp"
#import "parser.hpp"
#import "query_builder.hpp"

using namespace realm;

JSValueRef ResultsGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* jsException) {
    try {
        // index subscripting
        Results *results = RJSGetInternal<Results *>(object);
        size_t size = results->size();

        std::string indexStr = RJSStringForJSString(propertyName);
        if (indexStr == "length") {
            return JSValueMakeNumber(ctx, size);
        }

        auto row = results->get(RJSValidatedPositiveIndex(indexStr));
        if (!row) {
            return JSValueMakeNull(ctx);
        }

        return RJSObjectCreate(ctx, Object(results->get_realm(), results->object_schema, row));
    }
    catch (std::out_of_range &exp) {
        // getters for nonexistent properties in JS should always return undefined
        return JSValueMakeUndefined(ctx);
    }
    catch (std::invalid_argument &exp) {
        // for stol failure this could be another property that is handled externally, so ignore
        return NULL;
    }
    catch (std::exception &exp) {
        if (jsException) {
            *jsException = RJSMakeError(ctx, exp);
        }
        return NULL;
    }
}

bool ResultsSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef *jsException) {
    try {
        std::string indexStr = RJSStringForJSString(propertyName);
        if (indexStr != "length") {
            std::stol(RJSStringForJSString(propertyName));
        }

        // attempts to assign to 'length' or an index should throw an exception
        if (jsException) {
            *jsException = RJSMakeError(ctx, "Results objects are readonly");
        }
    }
    catch (std::invalid_argument &exp) {
        // for stol failure this could be another property that is handled externally, so ignore
    }
    return false;
}

void ResultsPropertyNames(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames) {
    Results *results = RJSGetInternal<Results *>(object);
    size_t size = results->size();

    char str[32];
    for (size_t i = 0; i < size; i++) {
        sprintf(str, "%zu", i);
        JSStringRef name = JSStringCreateWithUTF8CString(str);
        JSPropertyNameAccumulatorAddName(propertyNames, name);
        JSStringRelease(name);
    }
}

JSValueRef ResultsStaticCopy(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
    try {
        Results *results = RJSGetInternal<Results *>(thisObject);
        RJSValidateArgumentCount(argumentCount, 0);

        Results *copy = new Results(*results);
        copy->set_live(false);

        return RJSWrapObject<Results *>(ctx, RJSResultsClass(), copy);
    }
    catch (std::exception &exp) {
        if (jsException) {
            *jsException = RJSMakeError(ctx, exp);
        }
    }
    return NULL;
}

JSValueRef ResultsSortByProperty(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
    try {
        Results *results = RJSGetInternal<Results *>(thisObject);
        RJSValidateArgumentRange(argumentCount, 1, 2);

        std::string propName = RJSValidatedStringForValue(ctx, arguments[0]);
        const Property *prop = results->object_schema.property_for_name(propName);
        if (!prop) {
            throw std::runtime_error("Property '" + propName + "' does not exist on object type '" + results->object_schema.name + "'");
        }

        bool ascending = true;
        if (argumentCount == 2) {
            ascending = JSValueToBoolean(ctx, arguments[1]);
        }

        *results = results->sort({{prop->table_column}, {ascending}});
    }
    catch (std::exception &exp) {
        if (jsException) {
            *jsException = RJSMakeError(ctx, exp);
        }
    }
    return NULL;
}

JSObjectRef RJSResultsCreate(JSContextRef ctx, SharedRealm realm, std::string className) {
    TableRef table = ObjectStore::table_for_object_type(realm->read_group(), className);
    auto object_schema = realm->config().schema->find(className);
    if (object_schema == realm->config().schema->end()) {
        throw std::runtime_error("Object type '" + className + "' not present in Realm.");
    }
    return RJSWrapObject<Results *>(ctx, RJSResultsClass(), new Results(realm, *object_schema, *table));
}

JSObjectRef RJSResultsCreate(JSContextRef ctx, SharedRealm realm, std::string className, std::string queryString, std::vector<JSValueRef> args) {
    TableRef table = ObjectStore::table_for_object_type(realm->read_group(), className);
    Query query = table->where();
    const Schema &schema = *realm->config().schema;
    auto object_schema = schema.find(className);
    if (object_schema == schema.end()) {
        throw std::runtime_error("Object type '" + className + "' not present in Realm.");
    }
    parser::Predicate predicate = parser::parse(queryString);
    query_builder::ArgumentConverter<JSValueRef, JSContextRef> arguments(ctx, args);
    query_builder::apply_predicate(query, predicate, arguments, schema, object_schema->name);

    return RJSWrapObject<Results *>(ctx, RJSResultsClass(), new Results(realm, *object_schema, std::move(query)));
}

JSObjectRef RJSResultsCreate(JSContextRef ctx, SharedRealm realm, const ObjectSchema &objectSchema, const Query &query, bool live) {
    Results *results = new Results(realm, objectSchema, query);
    results->set_live(live);

    return RJSWrapObject<Results *>(ctx, RJSResultsClass(), results);
}

static const JSStaticFunction RJSResultsFuncs[] = {
    {"snapshot", ResultsStaticCopy, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
    {"sortByProperty", ResultsSortByProperty, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
    {NULL, NULL},
};

JSClassRef RJSResultsClass() {
    static JSClassRef s_objectClass = RJSCreateWrapperClass<Results *>("Results", ResultsGetProperty, ResultsSetProperty, RJSResultsFuncs, ResultsPropertyNames);
    return s_objectClass;
}
<commit_msg>Explicitly check if row is attached<commit_after>/* Copyright 2015 Realm Inc - All Rights Reserved
 * Proprietary and Confidential
 */

#import "js_results.hpp"
#import "js_object.hpp"
#import "object_accessor.hpp"
#import "results.hpp"
#import "parser.hpp"
#import "query_builder.hpp"

using namespace realm;

JSValueRef ResultsGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* jsException) {
    try {
        // index subscripting
        Results *results = RJSGetInternal<Results *>(object);
        size_t size = results->size();

        std::string indexStr = RJSStringForJSString(propertyName);
        if (indexStr == "length") {
            return JSValueMakeNumber(ctx, size);
        }

        auto row = results->get(RJSValidatedPositiveIndex(indexStr));
        if (!row.is_attached()) {
            return JSValueMakeNull(ctx);
        }

        return RJSObjectCreate(ctx, Object(results->get_realm(), results->object_schema, row));
    }
    catch (std::out_of_range &exp) {
        // getters for nonexistent properties in JS should always return undefined
        return JSValueMakeUndefined(ctx);
    }
    catch (std::invalid_argument &exp) {
        // for stol failure this could be another property that is handled externally, so ignore
        return NULL;
    }
    catch (std::exception &exp) {
        if (jsException) {
            *jsException = RJSMakeError(ctx, exp);
        }
        return NULL;
    }
}

bool ResultsSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef *jsException) {
    try {
        std::string indexStr = RJSStringForJSString(propertyName);
        if (indexStr != "length") {
            std::stol(RJSStringForJSString(propertyName));
        }

        // attempts to assign to 'length' or an index should throw an exception
        if (jsException) {
            *jsException = RJSMakeError(ctx, "Results objects are readonly");
        }
    }
    catch (std::invalid_argument &exp) {
        // for stol failure this could be another property that is handled externally, so ignore
    }
    return false;
}

void ResultsPropertyNames(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames) {
    Results *results = RJSGetInternal<Results *>(object);
    size_t size = results->size();

    char str[32];
    for (size_t i = 0; i < size; i++) {
        sprintf(str, "%zu", i);
        JSStringRef name = JSStringCreateWithUTF8CString(str);
        JSPropertyNameAccumulatorAddName(propertyNames, name);
        JSStringRelease(name);
    }
}

JSValueRef ResultsStaticCopy(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
    try {
        Results *results = RJSGetInternal<Results *>(thisObject);
        RJSValidateArgumentCount(argumentCount, 0);

        Results *copy = new Results(*results);
        copy->set_live(false);

        return RJSWrapObject<Results *>(ctx, RJSResultsClass(), copy);
    }
    catch (std::exception &exp) {
        if (jsException) {
            *jsException = RJSMakeError(ctx, exp);
        }
    }
    return NULL;
}

JSValueRef ResultsSortByProperty(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
    try {
        Results *results = RJSGetInternal<Results *>(thisObject);
        RJSValidateArgumentRange(argumentCount, 1, 2);

        std::string propName = RJSValidatedStringForValue(ctx, arguments[0]);
        const Property *prop = results->object_schema.property_for_name(propName);
        if (!prop) {
            throw std::runtime_error("Property '" + propName + "' does not exist on object type '" + results->object_schema.name + "'");
        }

        bool ascending = true;
        if (argumentCount == 2) {
            ascending = JSValueToBoolean(ctx, arguments[1]);
        }

        *results = results->sort({{prop->table_column}, {ascending}});
    }
    catch (std::exception &exp) {
        if (jsException) {
            *jsException = RJSMakeError(ctx, exp);
        }
    }
    return NULL;
}

JSObjectRef RJSResultsCreate(JSContextRef ctx, SharedRealm realm, std::string className) {
    TableRef table = ObjectStore::table_for_object_type(realm->read_group(), className);
    auto object_schema = realm->config().schema->find(className);
    if (object_schema == realm->config().schema->end()) {
        throw std::runtime_error("Object type '" + className + "' not present in Realm.");
    }
    return RJSWrapObject<Results *>(ctx, RJSResultsClass(), new Results(realm, *object_schema, *table));
}

JSObjectRef RJSResultsCreate(JSContextRef ctx, SharedRealm realm, std::string className, std::string queryString, std::vector<JSValueRef> args) {
    TableRef table = ObjectStore::table_for_object_type(realm->read_group(), className);
    Query query = table->where();
    const Schema &schema = *realm->config().schema;
    auto object_schema = schema.find(className);
    if (object_schema == schema.end()) {
        throw std::runtime_error("Object type '" + className + "' not present in Realm.");
    }
    parser::Predicate predicate = parser::parse(queryString);
    query_builder::ArgumentConverter<JSValueRef, JSContextRef> arguments(ctx, args);
    query_builder::apply_predicate(query, predicate, arguments, schema, object_schema->name);

    return RJSWrapObject<Results *>(ctx, RJSResultsClass(), new Results(realm, *object_schema, std::move(query)));
}

JSObjectRef RJSResultsCreate(JSContextRef ctx, SharedRealm realm, const ObjectSchema &objectSchema, const Query &query, bool live) {
    Results *results = new Results(realm, objectSchema, query);
    results->set_live(live);

    return RJSWrapObject<Results *>(ctx, RJSResultsClass(), results);
}

static const JSStaticFunction RJSResultsFuncs[] = {
    {"snapshot", ResultsStaticCopy, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
    {"sortByProperty", ResultsSortByProperty, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
    {NULL, NULL},
};

JSClassRef RJSResultsClass() {
    static JSClassRef s_objectClass = RJSCreateWrapperClass<Results *>("Results", ResultsGetProperty, ResultsSetProperty, RJSResultsFuncs, ResultsPropertyNames);
    return s_objectClass;
}
<|endoftext|>


<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Point Cloud Library (PCL) - www.pointclouds.org
 *  Copyright (c) 2010-2011, Willow Garage, Inc.
 *
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 * $Id$
 */

#include <sensor_msgs/PointCloud2.h>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/console/print.h>
#include <pcl/console/parse.h>
#include <pcl/console/time.h>
#include <pcl/filters/passthrough.h>

using namespace pcl;
using namespace pcl::io;
using namespace pcl::console;

float default_min = 0.0f,
      default_max = 1.0f;
bool default_inside = true;
bool default_keep_organized = true;
std::string default_field_name = "z";

void
printHelp (int, char **argv)
{
  print_error ("Syntax is: %s input.pcd output.pcd <options>\n", argv[0]);
  print_info ("  where options are:\n");
  print_info ("                     -field X = the field of the point cloud we want to apply the filter to (default: ");
  print_value ("%s", default_field_name.c_str ()); print_info (")\n");
  print_info ("                     -min X = lower limit of the filter (default: ");
  print_value ("%f", default_min); print_info (")\n");
  print_info ("                     -max X = upper limit of the filter (default: ");
  print_value ("%f", default_max); print_info (")\n");
  print_info ("                     -inside X = keep the points inside the [min, max] interval or not (default: ");
  print_value ("%d", default_inside); print_info (")\n");
}

bool
loadCloud (const std::string &filename, sensor_msgs::PointCloud2 &cloud)
{
  TicToc tt;
  print_highlight ("Loading "); print_value ("%s ", filename.c_str ());

  tt.tic ();
  if (loadPCDFile (filename, cloud) < 0)
    return (false);
  print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" ms : "); print_value ("%d", cloud.width * cloud.height); print_info (" points]\n");
  print_info ("Available dimensions: "); print_value ("%s\n", pcl::getFieldsList (cloud).c_str ());

  return (true);
}

void
compute (const sensor_msgs::PointCloud2::ConstPtr &input, sensor_msgs::PointCloud2 &output,
         std::string field_name, float min, float max, bool inside, bool keep_organized)
{
  // Estimate
  TicToc tt;
  tt.tic ();

  print_highlight (stderr, "Computing ");

  PassThrough<sensor_msgs::PointCloud2> passthrough_filter;
  passthrough_filter.setInputCloud (input);
  passthrough_filter.setFilterFieldName (field_name);
  passthrough_filter.setFilterLimits (min, max);
  passthrough_filter.setFilterLimitsNegative (!inside);
  passthrough_filter.setKeepOrganized (keep_organized);
  passthrough_filter.filter (output);

  print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" ms : "); print_value ("%d", output.width * output.height); print_info (" points]\n");
}

void
saveCloud (const std::string &filename, const sensor_msgs::PointCloud2 &output)
{
  TicToc tt;
  tt.tic ();

  print_highlight ("Saving "); print_value ("%s ", filename.c_str ());

  PCDWriter w;
  w.writeBinaryCompressed (filename, output);

  print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" ms : "); print_value ("%d", output.width * output.height); print_info (" points]\n");
}

/* ---[ */
int
main (int argc, char** argv)
{
  print_info ("Filter a point cloud using the pcl::PassThroughFilterEstimate. For more information, use: %s -h\n", argv[0]);

  if (argc < 3)
  {
    printHelp (argc, argv);
    return (-1);
  }

  // Parse the command line arguments for .pcd files
  std::vector<int> p_file_indices;
  p_file_indices = parse_file_extension_argument (argc, argv, ".pcd");
  if (p_file_indices.size () != 2)
  {
    print_error ("Need one input PCD file and one output PCD file to continue.\n");
    return (-1);
  }

  // Command line parsing
  float min = default_min, max = default_max;
  bool inside = default_inside;
  bool keep_organized = default_keep_organized;
  std::string field_name = default_field_name;
  parse_argument (argc, argv, "-min", min);
  parse_argument (argc, argv, "-max", max);
  parse_argument (argc, argv, "-inside", inside);
  parse_argument (argc, argv, "-field", field_name);
  parse_argument (argc, argv, "-keep", keep_organized);

  // Load the first file
  sensor_msgs::PointCloud2::Ptr cloud (new sensor_msgs::PointCloud2);
  if (!loadCloud (argv[p_file_indices[0]], *cloud))
    return (-1);

  // Perform the feature estimation
  sensor_msgs::PointCloud2 output;
  compute (cloud, output, field_name, min, max, inside, keep_organized);

  // Save into the second file
  saveCloud (argv[p_file_indices[1]], output);
}
<commit_msg>better help<commit_after>/*
 * Software License Agreement (BSD License)
 *
 *  Point Cloud Library (PCL) - www.pointclouds.org
 *  Copyright (c) 2010-2011, Willow Garage, Inc.
 *
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 * $Id$
 */

#include <sensor_msgs/PointCloud2.h>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/console/print.h>
#include <pcl/console/parse.h>
#include <pcl/console/time.h>
#include <pcl/filters/passthrough.h>

using namespace pcl;
using namespace pcl::io;
using namespace pcl::console;

float default_min = 0.0f,
      default_max = 1.0f;
bool default_inside = true;
bool default_keep_organized = true;
std::string default_field_name = "z";

void
printHelp (int, char **argv)
{
  print_error ("Syntax is: %s input.pcd output.pcd <options>\n", argv[0]);
  print_info ("  where options are:\n");
  print_info ("                     -field X = the field of the point cloud we want to apply the filter to (default: ");
  print_value ("%s", default_field_name.c_str ()); print_info (")\n");
  print_info ("                     -min X = lower limit of the filter (default: ");
  print_value ("%f", default_min); print_info (")\n");
  print_info ("                     -max X = upper limit of the filter (default: ");
  print_value ("%f", default_max); print_info (")\n");
  print_info ("                     -inside X = keep the points inside the [min, max] interval or not (default: ");
  print_value ("%d", default_inside); print_info (")\n");
  print_info ("                     -keep 0/1 = keep the points organized (1) or not (default: ");
  print_value ("%d", default_keep_organized); print_info (")\n");
}

bool
loadCloud (const std::string &filename, sensor_msgs::PointCloud2 &cloud)
{
  TicToc tt;
  print_highlight ("Loading "); print_value ("%s ", filename.c_str ());

  tt.tic ();
  if (loadPCDFile (filename, cloud) < 0)
    return (false);
  print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" ms : "); print_value ("%d", cloud.width * cloud.height); print_info (" points]\n");
  print_info ("Available dimensions: "); print_value ("%s\n", pcl::getFieldsList (cloud).c_str ());

  return (true);
}

void
compute (const sensor_msgs::PointCloud2::ConstPtr &input, sensor_msgs::PointCloud2 &output,
         std::string field_name, float min, float max, bool inside, bool keep_organized)
{
  // Estimate
  TicToc tt;
  tt.tic ();

  print_highlight (stderr, "Computing ");

  PassThrough<sensor_msgs::PointCloud2> passthrough_filter;
  passthrough_filter.setInputCloud (input);
  passthrough_filter.setFilterFieldName (field_name);
  passthrough_filter.setFilterLimits (min, max);
  passthrough_filter.setFilterLimitsNegative (!inside);
  passthrough_filter.setKeepOrganized (keep_organized);
  passthrough_filter.filter (output);

  print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" ms : "); print_value ("%d", output.width * output.height); print_info (" points]\n");
}

void
saveCloud (const std::string &filename, const sensor_msgs::PointCloud2 &output)
{
  TicToc tt;
  tt.tic ();

  print_highlight ("Saving "); print_value ("%s ", filename.c_str ());

  PCDWriter w;
  w.writeBinaryCompressed (filename, output);

  print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" ms : "); print_value ("%d", output.width * output.height); print_info (" points]\n");
}

/* ---[ */
int
main (int argc, char** argv)
{
  print_info ("Filter a point cloud using the pcl::PassThroughFilterEstimate. For more information, use: %s -h\n", argv[0]);

  if (argc < 3)
  {
    printHelp (argc, argv);
    return (-1);
  }

  // Parse the command line arguments for .pcd files
  std::vector<int> p_file_indices;
  p_file_indices = parse_file_extension_argument (argc, argv, ".pcd");
  if (p_file_indices.size () != 2)
  {
    print_error ("Need one input PCD file and one output PCD file to continue.\n");
    return (-1);
  }

  // Command line parsing
  float min = default_min, max = default_max;
  bool inside = default_inside;
  bool keep_organized = default_keep_organized;
  std::string field_name = default_field_name;
  parse_argument (argc, argv, "-min", min);
  parse_argument (argc, argv, "-max", max);
  parse_argument (argc, argv, "-inside", inside);
  parse_argument (argc, argv, "-field", field_name);
  parse_argument (argc, argv, "-keep", keep_organized);

  // Load the first file
  sensor_msgs::PointCloud2::Ptr cloud (new sensor_msgs::PointCloud2);
  if (!loadCloud (argv[p_file_indices[0]], *cloud))
    return (-1);

  // Perform the feature estimation
  sensor_msgs::PointCloud2 output;
  compute (cloud, output, field_name, min, max, inside, keep_organized);

  // Save into the second file
  saveCloud (argv[p_file_indices[1]], output);
}
<|endoftext|>


<commit_before>/***************************************************************************
*   Copyright (C) 2003-2004 Adam Geitgey <adam@rootnode.org>              *
*   Copyright (C) 2003 Hans Karlsson <karlsson.h@home.se>                 *
*   Copyright (C) 2007 Alexander Wiedenbruch <mail@wiedenbruch.de>        *
*   Copyright (C) 2007 Matt Broadstone <mbroadst@gmail.com>               *
*                                                                         *
*   This program 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 2 of the License, or     *
*   (at your option) any later version.                                   *
***************************************************************************/
#include "karambaapp.h"
#include "karambaapp.moc"

#include "superkarambasettings.h"
#include "mainwidget.h"
#include "themesdlg.h"
#include "karamba.h"
#include "superkarambaadaptor.h"
#include "karambamanager.h"

#include <QDesktopWidget>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QMenu>
#include <QDBusConnection>

#include <KUrl>
#include <KAction>
#include <KMessageBox>
#include <KDebug>
#include <KCmdLineArgs>
#include <KSystemTrayIcon>
#include <KHelpMenu>
#include <KStandardAction>
#include <KActionCollection>
#include <KMenu>

KarambaApplication::KarambaApplication(Display *display, Qt::HANDLE visual, Qt::HANDLE colormap)
        :   KUniqueApplication(display, visual, colormap),
        m_themesDialog(0)
{
    connect(KarambaManager::self(), SIGNAL(karambaStarted(QGraphicsItemGroup*)), this, SLOT(karambaStarted(QGraphicsItemGroup*)));
    connect(KarambaManager::self(), SIGNAL(karambaClosed(QGraphicsItemGroup*)), this, SLOT(karambaClosed(QGraphicsItemGroup*)));

    new SuperKarambaAdaptor(this);
    QDBusConnection dbus = QDBusConnection::sessionBus();
    dbus.registerObject("/SuperKaramba", this);
}

KarambaApplication::~KarambaApplication()
{
    delete m_themesDialog;
}

void KarambaApplication::checkCommandLine(KCmdLineArgs *args, QList<KUrl> &lst)
{
    /******
    *     Not a saved session - check for themes given on command line
    **/

    if (args->count() > 0) {
        for (int i = 0; i < (args->count()); i++) {
            if (args->arg(i) && *args->arg(i)) {
                KUrl url = args->url(i);
                lst.append(url);
            }
        }
    }
}

void KarambaApplication::startThemes(const QList<KUrl> &lst)
{
    foreach(KUrl url, lst) {
        new Karamba(url);
    }
}

void KarambaApplication::karambaStarted(QGraphicsItemGroup *item)
{
   Karamba *k = dynamic_cast<Karamba*>(item);
    if (!k) {
        return;
    }

   int instance = m_themesDialog->addTheme(k->prettyName(), k->theme().file());
    k->setInstance(instance);

    if (!SuperKarambaSettings::showSysTray()) {
        showKarambaMenuExtension();
    }

    buildToolTip();
}

void KarambaApplication::karambaClosed(QGraphicsItemGroup *item)
{
    Karamba *k = dynamic_cast<Karamba*>(item);
    if (!k) {
        return;
    }

    m_themesDialog->removeTheme(k->prettyName(), k->theme().file(), k->instance());

    buildToolTip();
}

void KarambaApplication::checkPreviousSession(QList<KUrl> &lst)
{
    if (isSessionRestored()) {
        KConfig* config = sessionConfig();
        QList<QString> themePaths = config->group("General Options").readEntry("OpenThemes", QList<QString>());
        foreach(QString path, themePaths) {
            lst.append(KUrl(path));
        }
    }
}

int KarambaApplication::newInstance()
{
    KCmdLineArgs *args = 0;
    QList<KUrl> lst;

    if (restoringSession()) {
        checkPreviousSession(lst);
    } else {
        args = KCmdLineArgs::parsedArgs();
        checkCommandLine(args, lst);
//        args->clear();
    }

    if (lst.count() > 0)
        startThemes(lst);
    else {
        if (m_themesDialog)
            m_themesDialog->show();
    }

    return 0;
}

void KarambaApplication::buildToolTip()
{
    if (!m_sysTrayIcon || !m_themesDialog)
        return;

    QStringList list = m_themesDialog->runningThemes();
    if (list.isEmpty()) {
        setToolTip();
        return;
    }

    QString toolTip("" + i18n("SuperKaramba") + "");
    toolTip += "
";

    bool firstRun = true;
    for (QStringList::Iterator it = list.begin(); it != list.end(); ++it) {
        if (firstRun) {
            toolTip += "
";
            toolTip += i18np("1 Running Theme:", "%1 Running Themes:", list.count());
            toolTip += "	" + (*it) + "
";
            firstRun = false;
        } else {
            toolTip += "
	" + (*it) + "
";
        }
    }
    toolTip += "
";

    setToolTip(toolTip);
}

void KarambaApplication::setToolTip(const QString &tip)
{
    m_sysTrayIcon->setToolTip(tip);
}

void KarambaApplication::toggleSystemTray()
{
    //kDebug() << k_funcinfo << endl;
    if (m_sysTrayIcon->isVisible()) {
        if (m_sysTrayIcon) {
            KMessageBox::information(m_themesDialog, i18n("<qt>Hiding the system tray icon will keep SuperKaramba running "
                                     "in background. To show it again use the theme menu.</qt>"),
                                     i18n("Hiding System Tray Icon"), "hideIcon");

            m_sysTrayIcon->hide();
        }
        showKarambaMenuExtension();
    } else {
        showKarambaMenuExtension(false);

        if (m_sysTrayIcon)
            m_sysTrayIcon->show();
    }

    SuperKarambaSettings::setShowSysTray(m_sysTrayIcon->isVisible());
    SuperKarambaSettings::self()->writeConfig();
}

void KarambaApplication::showKarambaMenuExtension(bool show)
{
    foreach(Karamba *k, KarambaManager::self()->getKarambas()) {
        if (show && !k->hasMenuExtension()) {
            KMenu *menu = new KMenu();
            menu->setTitle("SuperKaramba");

            menu->addAction(KIcon("superkaramba"),
                            i18n("Show System Tray Icon"), this,
                            SLOT(toggleSystemTray()),
                            Qt::CTRL + Qt::Key_S);

            menu->addAction(KIcon("get-hot-new-stuff"),
                            i18n("&Manage Themes..."), this,
                            SLOT(showThemesDialog()), Qt::CTRL + Qt::Key_M);

            menu->addAction(KIcon("application-exit"),
                            i18n("&Quit SuperKaramba"), this,
                            SLOT(quitSuperKaramba()), Qt::CTRL + Qt::Key_Q);
            k->setMenuExtension(menu);
        } else if (!show) {
            k->removeMenuExtension();
        }
    }
}

void KarambaApplication::showThemesDialog(QSystemTrayIcon::ActivationReason reason)
{
    if (reason == QSystemTrayIcon::Context)
        m_sysTrayIcon->show();
    else
        m_themesDialog->show();
}

void KarambaApplication::setupSysTray(KAboutData* about)
{
    KAction* action;

    //Create theme list window.
    //This will function as the main window for the tray icon
    m_themesDialog = new ThemesDlg();

    //Set up systray icon
    m_sysTrayIcon = new KSystemTrayIcon();

    QMenu *menu = m_sysTrayIcon->contextMenu();
    menu->addAction(KIcon("superkaramba"),
                    i18n("Hide System Tray Icon"), this,
                    SLOT(toggleSystemTray()));

    menu->addSeparator();

    m_helpMenu = new KHelpMenu(m_themesDialog, about);
    action = KStandardAction::help(m_helpMenu,
                                   SLOT(appHelpActivated()),
                                   m_sysTrayIcon->actionCollection());

    menu->addAction(action);

    action = KStandardAction::aboutApp(m_helpMenu, SLOT(aboutApplication()),
                                       m_sysTrayIcon->actionCollection());
    menu->addAction(action);

    action = KStandardAction::aboutKDE(m_helpMenu, SLOT(aboutKDE()),
                                       m_sysTrayIcon->actionCollection());
    menu->addAction(action);

    m_sysTrayIcon->setIcon(m_sysTrayIcon->loadIcon("superkaramba"));

    setToolTip();

    if (SuperKarambaSettings::showSysTray())
        m_sysTrayIcon->show();
    else
        m_sysTrayIcon->hide();

    connect(m_sysTrayIcon, SIGNAL(quitSelected()),
            this, SLOT(quitSuperKaramba()));
    connect(m_sysTrayIcon,
            SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
            this, SLOT(showThemesDialog(QSystemTrayIcon::ActivationReason)));
}

void KarambaApplication::sendDataToTheme(const QString &themeName, const QString &data, bool notify)
{
    if (notify) {
        themeNotify(themeName, data);
    } else {
        setIncomingData(themeName, data);
    }
}

//
// D-Bus methods
//
bool KarambaApplication::closeTheme(const QString &themeName)
{
    foreach(Karamba *k, KarambaManager::self()->getKarambas()) {
        if (k->prettyName() == themeName) {
            k->closeWidget();
            return true;
        }
    }

    return false;
}

void KarambaApplication::hideSystemTray(bool hide)
{
    if (hide && m_sysTrayIcon->isVisible()) {
        toggleSystemTray();
    } else if (!hide && !m_sysTrayIcon->isVisible()) {
        toggleSystemTray();
    }
}

void KarambaApplication::openNamedTheme(const QString &file, const QString &themeName, bool subTheme)
{
    Karamba *k = new Karamba(KUrl(file), 0, -1, subTheme);
    k->setPrettyName(themeName);
    connect(k, SIGNAL(widgetStarted(Karamba*, bool, bool)),
        this, SLOT(karambaStarted(Karamba*, bool, bool)));
}

void KarambaApplication::openTheme(const QString &file)
{
    Karamba *k = new Karamba(KUrl(file));
    connect(k, SIGNAL(widgetStarted(Karamba*, bool, bool)),
        this, SLOT(karambaStarted(Karamba*, bool, bool)));
}

void KarambaApplication::quitSuperKaramba()
{
    delete KarambaManager::self();

    if (m_themesDialog) {
        m_themesDialog->saveUserAddedThemes();
    }

    quit();
}

bool KarambaApplication::setIncomingData(const QString &prettyThemeName, const QString &data)
{
    Karamba *k = KarambaManager::self()->getKarambaByName(prettyThemeName);
    if (k == 0) {
        return false;
    }

    k->setIncomingData(data);

    return true;
}

void KarambaApplication::showThemeDialog()
{
    showThemesDialog();
}

bool KarambaApplication::themeNotify(const QString &prettyThemeName, const QString &data)
{
    Karamba *k = KarambaManager::self()->getKarambaByName(prettyThemeName);
    if (k == 0) {
        return false;
    }

    k->notifyTheme(prettyThemeName, data);

    return true;
}

<commit_msg>fix crash (CID 3520)<commit_after>/***************************************************************************
*   Copyright (C) 2003-2004 Adam Geitgey <adam@rootnode.org>              *
*   Copyright (C) 2003 Hans Karlsson <karlsson.h@home.se>                 *
*   Copyright (C) 2007 Alexander Wiedenbruch <mail@wiedenbruch.de>        *
*   Copyright (C) 2007 Matt Broadstone <mbroadst@gmail.com>               *
*                                                                         *
*   This program 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 2 of the License, or     *
*   (at your option) any later version.                                   *
***************************************************************************/
#include "karambaapp.h"
#include "karambaapp.moc"

#include "superkarambasettings.h"
#include "mainwidget.h"
#include "themesdlg.h"
#include "karamba.h"
#include "superkarambaadaptor.h"
#include "karambamanager.h"

#include <QDesktopWidget>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QMenu>
#include <QDBusConnection>

#include <KUrl>
#include <KAction>
#include <KMessageBox>
#include <KDebug>
#include <KCmdLineArgs>
#include <KSystemTrayIcon>
#include <KHelpMenu>
#include <KStandardAction>
#include <KActionCollection>
#include <KMenu>

KarambaApplication::KarambaApplication(Display *display, Qt::HANDLE visual, Qt::HANDLE colormap)
        :   KUniqueApplication(display, visual, colormap),
        m_themesDialog(0)
{
    connect(KarambaManager::self(), SIGNAL(karambaStarted(QGraphicsItemGroup*)), this, SLOT(karambaStarted(QGraphicsItemGroup*)));
    connect(KarambaManager::self(), SIGNAL(karambaClosed(QGraphicsItemGroup*)), this, SLOT(karambaClosed(QGraphicsItemGroup*)));

    new SuperKarambaAdaptor(this);
    QDBusConnection dbus = QDBusConnection::sessionBus();
    dbus.registerObject("/SuperKaramba", this);
}

KarambaApplication::~KarambaApplication()
{
    delete m_themesDialog;
}

void KarambaApplication::checkCommandLine(KCmdLineArgs *args, QList<KUrl> &lst)
{
    /******
    *     Not a saved session - check for themes given on command line
    **/

    if (args->count() > 0) {
        for (int i = 0; i < (args->count()); i++) {
            if (args->arg(i) && *args->arg(i)) {
                KUrl url = args->url(i);
                lst.append(url);
            }
        }
    }
}

void KarambaApplication::startThemes(const QList<KUrl> &lst)
{
    foreach(KUrl url, lst) {
        new Karamba(url);
    }
}

void KarambaApplication::karambaStarted(QGraphicsItemGroup *item)
{
   Karamba *k = dynamic_cast<Karamba*>(item);
    if (!k) {
        return;
    }

   int instance = m_themesDialog->addTheme(k->prettyName(), k->theme().file());
    k->setInstance(instance);

    if (!SuperKarambaSettings::showSysTray()) {
        showKarambaMenuExtension();
    }

    buildToolTip();
}

void KarambaApplication::karambaClosed(QGraphicsItemGroup *item)
{
    Karamba *k = dynamic_cast<Karamba*>(item);
    if (!k) {
        return;
    }

    m_themesDialog->removeTheme(k->prettyName(), k->theme().file(), k->instance());

    buildToolTip();
}

void KarambaApplication::checkPreviousSession(QList<KUrl> &lst)
{
    if (isSessionRestored()) {
        KConfig* config = sessionConfig();
        QList<QString> themePaths = config->group("General Options").readEntry("OpenThemes", QList<QString>());
        foreach(QString path, themePaths) {
            lst.append(KUrl(path));
        }
    }
}

int KarambaApplication::newInstance()
{
    KCmdLineArgs *args = 0;
    QList<KUrl> lst;

    if (restoringSession()) {
        checkPreviousSession(lst);
    } else {
        args = KCmdLineArgs::parsedArgs();
        checkCommandLine(args, lst);
//        args->clear();
    }

    if (lst.count() > 0)
        startThemes(lst);
    else {
        if (m_themesDialog)
            m_themesDialog->show();
    }

    return 0;
}

void KarambaApplication::buildToolTip()
{
    if (!m_sysTrayIcon || !m_themesDialog)
        return;

    QStringList list = m_themesDialog->runningThemes();
    if (list.isEmpty()) {
        setToolTip();
        return;
    }

    QString toolTip("" + i18n("SuperKaramba") + "");
    toolTip += "
";

    bool firstRun = true;
    for (QStringList::Iterator it = list.begin(); it != list.end(); ++it) {
        if (firstRun) {
            toolTip += "
";
            toolTip += i18np("1 Running Theme:", "%1 Running Themes:", list.count());
            toolTip += "	" + (*it) + "
";
            firstRun = false;
        } else {
            toolTip += "
	" + (*it) + "
";
        }
    }
    toolTip += "
";

    setToolTip(toolTip);
}

void KarambaApplication::setToolTip(const QString &tip)
{
    m_sysTrayIcon->setToolTip(tip);
}

void KarambaApplication::toggleSystemTray()
{
    //kDebug() << k_funcinfo << endl;
    if (m_sysTrayIcon->isVisible()) {
        if (m_sysTrayIcon) {
            KMessageBox::information(m_themesDialog, i18n("<qt>Hiding the system tray icon will keep SuperKaramba running "
                                     "in background. To show it again use the theme menu.</qt>"),
                                     i18n("Hiding System Tray Icon"), "hideIcon");

            m_sysTrayIcon->hide();
        }
        showKarambaMenuExtension();
    } else {
        showKarambaMenuExtension(false);

        if (m_sysTrayIcon)
            m_sysTrayIcon->show();
    }

    SuperKarambaSettings::setShowSysTray(m_sysTrayIcon ? m_sysTrayIcon->isVisible() : false);
    SuperKarambaSettings::self()->writeConfig();
}

void KarambaApplication::showKarambaMenuExtension(bool show)
{
    foreach(Karamba *k, KarambaManager::self()->getKarambas()) {
        if (show && !k->hasMenuExtension()) {
            KMenu *menu = new KMenu();
            menu->setTitle("SuperKaramba");

            menu->addAction(KIcon("superkaramba"),
                            i18n("Show System Tray Icon"), this,
                            SLOT(toggleSystemTray()),
                            Qt::CTRL + Qt::Key_S);

            menu->addAction(KIcon("get-hot-new-stuff"),
                            i18n("&Manage Themes..."), this,
                            SLOT(showThemesDialog()), Qt::CTRL + Qt::Key_M);

            menu->addAction(KIcon("application-exit"),
                            i18n("&Quit SuperKaramba"), this,
                            SLOT(quitSuperKaramba()), Qt::CTRL + Qt::Key_Q);
            k->setMenuExtension(menu);
        } else if (!show) {
            k->removeMenuExtension();
        }
    }
}

void KarambaApplication::showThemesDialog(QSystemTrayIcon::ActivationReason reason)
{
    if (reason == QSystemTrayIcon::Context)
        m_sysTrayIcon->show();
    else
        m_themesDialog->show();
}

void KarambaApplication::setupSysTray(KAboutData* about)
{
    KAction* action;

    //Create theme list window.
    //This will function as the main window for the tray icon
    m_themesDialog = new ThemesDlg();

    //Set up systray icon
    m_sysTrayIcon = new KSystemTrayIcon();

    QMenu *menu = m_sysTrayIcon->contextMenu();
    menu->addAction(KIcon("superkaramba"),
                    i18n("Hide System Tray Icon"), this,
                    SLOT(toggleSystemTray()));

    menu->addSeparator();

    m_helpMenu = new KHelpMenu(m_themesDialog, about);
    action = KStandardAction::help(m_helpMenu,
                                   SLOT(appHelpActivated()),
                                   m_sysTrayIcon->actionCollection());

    menu->addAction(action);

    action = KStandardAction::aboutApp(m_helpMenu, SLOT(aboutApplication()),
                                       m_sysTrayIcon->actionCollection());
    menu->addAction(action);

    action = KStandardAction::aboutKDE(m_helpMenu, SLOT(aboutKDE()),
                                       m_sysTrayIcon->actionCollection());
    menu->addAction(action);

    m_sysTrayIcon->setIcon(m_sysTrayIcon->loadIcon("superkaramba"));

    setToolTip();

    if (SuperKarambaSettings::showSysTray())
        m_sysTrayIcon->show();
    else
        m_sysTrayIcon->hide();

    connect(m_sysTrayIcon, SIGNAL(quitSelected()),
            this, SLOT(quitSuperKaramba()));
    connect(m_sysTrayIcon,
            SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
            this, SLOT(showThemesDialog(QSystemTrayIcon::ActivationReason)));
}

void KarambaApplication::sendDataToTheme(const QString &themeName, const QString &data, bool notify)
{
    if (notify) {
        themeNotify(themeName, data);
    } else {
        setIncomingData(themeName, data);
    }
}

//
// D-Bus methods
//
bool KarambaApplication::closeTheme(const QString &themeName)
{
    foreach(Karamba *k, KarambaManager::self()->getKarambas()) {
        if (k->prettyName() == themeName) {
            k->closeWidget();
            return true;
        }
    }

    return false;
}

void KarambaApplication::hideSystemTray(bool hide)
{
    if (hide && m_sysTrayIcon->isVisible()) {
        toggleSystemTray();
    } else if (!hide && !m_sysTrayIcon->isVisible()) {
        toggleSystemTray();
    }
}

void KarambaApplication::openNamedTheme(const QString &file, const QString &themeName, bool subTheme)
{
    Karamba *k = new Karamba(KUrl(file), 0, -1, subTheme);
    k->setPrettyName(themeName);
    connect(k, SIGNAL(widgetStarted(Karamba*, bool, bool)),
        this, SLOT(karambaStarted(Karamba*, bool, bool)));
}

void KarambaApplication::openTheme(const QString &file)
{
    Karamba *k = new Karamba(KUrl(file));
    connect(k, SIGNAL(widgetStarted(Karamba*, bool, bool)),
        this, SLOT(karambaStarted(Karamba*, bool, bool)));
}

void KarambaApplication::quitSuperKaramba()
{
    delete KarambaManager::self();

    if (m_themesDialog) {
        m_themesDialog->saveUserAddedThemes();
    }

    quit();
}

bool KarambaApplication::setIncomingData(const QString &prettyThemeName, const QString &data)
{
    Karamba *k = KarambaManager::self()->getKarambaByName(prettyThemeName);
    if (k == 0) {
        return false;
    }

    k->setIncomingData(data);

    return true;
}

void KarambaApplication::showThemeDialog()
{
    showThemesDialog();
}

bool KarambaApplication::themeNotify(const QString &prettyThemeName, const QString &data)
{
    Karamba *k = KarambaManager::self()->getKarambaByName(prettyThemeName);
    if (k == 0) {
        return false;
    }

    k->notifyTheme(prettyThemeName, data);

    return true;
}

<|endoftext|>


<commit_before>/**
 ** \file scheduler/job.hxx
 ** \brief Inline implementation of scheduler::Job.
 */

#ifndef SCHEDULER_JOB_HXX
# define SCHEDULER_JOB_HXX

# include <cassert>
# include "scheduler/scheduler.hh"
# include "scheduler/coroutine.hh"

namespace scheduler
{

  inline
  Job::Job (Scheduler& scheduler, const libport::Symbol& name)
    : state_ (to_start),
      frozen_since_ (0),
      time_shift_ (0),
      scheduler_ (&scheduler),
      myself_ (this),
      name_ (name == SYMBOL () ? libport::Symbol::fresh (SYMBOL (job)) : name),
      coro_ (coroutine_new ()),
      non_interruptible_ (false),
      side_effect_free_ (false),
      pending_exception_ (0)
  {
  }

  inline
  Job::Job (const Job& model, const libport::Symbol& name)
    : state_ (to_start),
      frozen_since_ (0),
      time_shift_ (model.time_shift_),
      scheduler_ (model.scheduler_),
      myself_ (this),
      name_ (name == SYMBOL () ? libport::Symbol::fresh (model.name_get ()) : name),
      coro_ (coroutine_new ()),
      tags_ (model.tags_),
      non_interruptible_ (false),
      side_effect_free_ (false),
      pending_exception_ (0)
  {
  }

  inline
  Job::~Job ()
  {
    scheduler_->unschedule_job (this);
    pending_exception_ = 0;
    coroutine_free (coro_);
  }

  inline Scheduler&
  Job::scheduler_get () const
  {
    return *scheduler_;
  }

  inline void
  Job::terminate ()
  {
  }

  inline bool
  Job::terminated () const
  {
    return state_ == zombie;
  }

  inline void
  Job::yield ()
  {
    // The only case where we yield while being non-interruptible
    // is when we get frozen. This is used to suspend a task
    // and resume it in non-interruptible contexts.
    if (non_interruptible_ && !frozen ())
      return;

    state_ = running;
    scheduler_->resume_scheduler (this);
  }

  inline void
  Job::yield_until (libport::utime_t deadline)
  {
    if (non_interruptible_)
      throw object::SchedulingError ("attempt to sleep in non-interruptible code");

    state_ = sleeping;
    deadline_ = deadline;
    scheduler_->resume_scheduler (this);
  }

  inline Coro*
  Job::coro_get () const
  {
    assert (coro_);
    return coro_;
  }

  inline void
  Job::start_job ()
  {
    assert (state_ == to_start);
    scheduler_->add_job (this);
  }

  inline void
  Job::side_effect_free_set (bool s)
  {
    side_effect_free_ = s;
  }

  inline bool
  Job::side_effect_free_get () const
  {
    return side_effect_free_;
  }

  inline void
  Job::link (Job* other)
  {
    links_.push_back (other);
    other->links_.push_back (this);
  }

  inline void
  Job::unlink (Job* other)
  {
    links_.remove (other);
    other->links_.remove (this);
  }

  inline const libport::Symbol&
  Job::name_get () const
  {
    return name_;
  }

  inline bool
  Job::non_interruptible_get () const
  {
    return non_interruptible_;
  }

  inline void
  Job::non_interruptible_set (bool ni)
  {
    non_interruptible_ = ni;
  }

  inline void
  Job::check_stack_space () const
  {
    if (coroutine_stack_space_almost_gone (coro_))
      throw object::StackExhaustedError ("stack space exhausted");
  }

  inline job_state
  Job::state_get () const
  {
    return state_;
  }

  inline void
  Job::state_set (job_state state)
  {
    state_ = state;
  }

  inline libport::utime_t
  Job::deadline_get () const
  {
    return deadline_;
  }

  inline rJob
  Job::myself_get () const
  {
    return myself_;
  }

  inline void
  Job::notice_frozen (libport::utime_t current_time)
  {
    if (!frozen_since_)
      frozen_since_ = current_time;
  }

  inline void
  Job::notice_not_frozen (libport::utime_t current_time)
  {
    if (frozen_since_ && state_ == sleeping)
    {
      libport::utime_t time_spent_frozen = current_time - frozen_since_;
      time_shift_ += time_spent_frozen;
      deadline_ += time_spent_frozen;
    }
    frozen_since_ = 0;
  }

  inline libport::utime_t
  Job::frozen_since_get () const
  {
    return frozen_since_;
  }

  inline libport::utime_t
  Job::time_shift_get () const
  {
    return time_shift_;
  }

  inline void
  Job::time_shift_set (libport::utime_t ts)
  {
    time_shift_ = ts;
  }

  inline std::ostream&
  operator<< (std::ostream& o, const Job& j)
  {
    return o << "Job(" << j.name_get () << ")";
  }

  inline const char*
  state_name (job_state state)
  {
#define CASE(State) case State: return #State;
    switch (state)
    {
      CASE(to_start)
      CASE (running)
      CASE(sleeping)
      CASE(waiting)
      CASE(joining)
      CASE(zombie)
    }
#undef CASE
    return "<unknown state>";
  }

} // namespace scheduler

#endif // !SCHEDULER_JOB_HXX
<commit_msg>Compute time shift even if not sleeping<commit_after>/**
 ** \file scheduler/job.hxx
 ** \brief Inline implementation of scheduler::Job.
 */

#ifndef SCHEDULER_JOB_HXX
# define SCHEDULER_JOB_HXX

# include <cassert>
# include "scheduler/scheduler.hh"
# include "scheduler/coroutine.hh"

namespace scheduler
{

  inline
  Job::Job (Scheduler& scheduler, const libport::Symbol& name)
    : state_ (to_start),
      frozen_since_ (0),
      time_shift_ (0),
      scheduler_ (&scheduler),
      myself_ (this),
      name_ (name == SYMBOL () ? libport::Symbol::fresh (SYMBOL (job)) : name),
      coro_ (coroutine_new ()),
      non_interruptible_ (false),
      side_effect_free_ (false),
      pending_exception_ (0)
  {
  }

  inline
  Job::Job (const Job& model, const libport::Symbol& name)
    : state_ (to_start),
      frozen_since_ (0),
      time_shift_ (model.time_shift_),
      scheduler_ (model.scheduler_),
      myself_ (this),
      name_ (name == SYMBOL () ? libport::Symbol::fresh (model.name_get ()) : name),
      coro_ (coroutine_new ()),
      tags_ (model.tags_),
      non_interruptible_ (false),
      side_effect_free_ (false),
      pending_exception_ (0)
  {
  }

  inline
  Job::~Job ()
  {
    scheduler_->unschedule_job (this);
    pending_exception_ = 0;
    coroutine_free (coro_);
  }

  inline Scheduler&
  Job::scheduler_get () const
  {
    return *scheduler_;
  }

  inline void
  Job::terminate ()
  {
  }

  inline bool
  Job::terminated () const
  {
    return state_ == zombie;
  }

  inline void
  Job::yield ()
  {
    // The only case where we yield while being non-interruptible
    // is when we get frozen. This is used to suspend a task
    // and resume it in non-interruptible contexts.
    if (non_interruptible_ && !frozen ())
      return;

    state_ = running;
    scheduler_->resume_scheduler (this);
  }

  inline void
  Job::yield_until (libport::utime_t deadline)
  {
    if (non_interruptible_)
      throw object::SchedulingError ("attempt to sleep in non-interruptible code");

    state_ = sleeping;
    deadline_ = deadline;
    scheduler_->resume_scheduler (this);
  }

  inline Coro*
  Job::coro_get () const
  {
    assert (coro_);
    return coro_;
  }

  inline void
  Job::start_job ()
  {
    assert (state_ == to_start);
    scheduler_->add_job (this);
  }

  inline void
  Job::side_effect_free_set (bool s)
  {
    side_effect_free_ = s;
  }

  inline bool
  Job::side_effect_free_get () const
  {
    return side_effect_free_;
  }

  inline void
  Job::link (Job* other)
  {
    links_.push_back (other);
    other->links_.push_back (this);
  }

  inline void
  Job::unlink (Job* other)
  {
    links_.remove (other);
    other->links_.remove (this);
  }

  inline const libport::Symbol&
  Job::name_get () const
  {
    return name_;
  }

  inline bool
  Job::non_interruptible_get () const
  {
    return non_interruptible_;
  }

  inline void
  Job::non_interruptible_set (bool ni)
  {
    non_interruptible_ = ni;
  }

  inline void
  Job::check_stack_space () const
  {
    if (coroutine_stack_space_almost_gone (coro_))
      throw object::StackExhaustedError ("stack space exhausted");
  }

  inline job_state
  Job::state_get () const
  {
    return state_;
  }

  inline void
  Job::state_set (job_state state)
  {
    state_ = state;
  }

  inline libport::utime_t
  Job::deadline_get () const
  {
    return deadline_;
  }

  inline rJob
  Job::myself_get () const
  {
    return myself_;
  }

  inline void
  Job::notice_frozen (libport::utime_t current_time)
  {
    if (!frozen_since_)
      frozen_since_ = current_time;
  }

  inline void
  Job::notice_not_frozen (libport::utime_t current_time)
  {
    if (frozen_since_)
    {
      libport::utime_t time_spent_frozen = current_time - frozen_since_;
      time_shift_ += time_spent_frozen;
      if (state_ == sleeping)
	deadline_ += time_spent_frozen;
    }
    frozen_since_ = 0;
  }

  inline libport::utime_t
  Job::frozen_since_get () const
  {
    return frozen_since_;
  }

  inline libport::utime_t
  Job::time_shift_get () const
  {
    return time_shift_;
  }

  inline void
  Job::time_shift_set (libport::utime_t ts)
  {
    time_shift_ = ts;
  }

  inline std::ostream&
  operator<< (std::ostream& o, const Job& j)
  {
    return o << "Job(" << j.name_get () << ")";
  }

  inline const char*
  state_name (job_state state)
  {
#define CASE(State) case State: return #State;
    switch (state)
    {
      CASE(to_start)
      CASE (running)
      CASE(sleeping)
      CASE(waiting)
      CASE(joining)
      CASE(zombie)
    }
#undef CASE
    return "<unknown state>";
  }

} // namespace scheduler

#endif // !SCHEDULER_JOB_HXX
<|endoftext|>


<commit_before>#include "cube.hpp"

using namespace plush;

const glm::vec3 LEFT_BOTTOM_FRONT (-.5f, -.5f, .5f);
const glm::vec3 RIGHT_BOTTOM_FRONT( .5f, -.5f, .5f);
const glm::vec3 RIGHT_TOP_FRONT   ( .5f,  .5f, .5f);
const glm::vec3 LEFT_TOP_FRONT    (-.5f,  .5f, .5f);
const glm::vec3 LEFT_BOTTOM_BACK  (-.5f, -.5f, -.5f);
const glm::vec3 RIGHT_BOTTOM_BACK ( .5f, -.5f, -.5f);
const glm::vec3 RIGHT_TOP_BACK    ( .5f,  .5f, -.5f);
const glm::vec3 LEFT_TOP_BACK     (-.5f,  .5f, -.5f);

static const glm::vec3 cubeCoords[] = {

    // front side
    LEFT_BOTTOM_FRONT, RIGHT_BOTTOM_FRONT, RIGHT_TOP_FRONT, LEFT_TOP_FRONT,

    // back side
    LEFT_BOTTOM_BACK, RIGHT_BOTTOM_BACK, RIGHT_TOP_BACK, LEFT_TOP_BACK,

    // left side
    LEFT_BOTTOM_FRONT, LEFT_BOTTOM_BACK, LEFT_TOP_BACK, LEFT_TOP_FRONT,

    // right side
    RIGHT_BOTTOM_FRONT, RIGHT_BOTTOM_BACK, RIGHT_TOP_BACK, RIGHT_TOP_FRONT,

    // bottom side
    LEFT_BOTTOM_FRONT, RIGHT_BOTTOM_FRONT, RIGHT_BOTTOM_BACK, LEFT_BOTTOM_BACK,

    // top side
    LEFT_TOP_FRONT, RIGHT_TOP_FRONT, RIGHT_TOP_BACK, LEFT_TOP_BACK,
};

static const short cubeIndices[] = {
    0, 1, 2, 0, 2, 3,                   // front side
    4, 5, 6, 4, 6, 7,                   // back side
    8, 9, 10, 8, 10, 11,                // left side
    12, 13, 14, 12, 14, 15,             // right side
    16, 17, 18, 16, 18, 19,             // bottom side
    20, 21, 22, 20, 22, 23,             // top side
};

/////////////////////////////////////////////////////////////////////////////
// CubeModel
/////////////////////////////////////////////////////////////////////////////

CubeModel *CubeModel::s_instance = nullptr;

CubeModel::CubeModel()
    : coordsVBO(GL_STATIC_DRAW), indicesVBO(GL_STATIC_DRAW)
{
    VAOBinder vaoBinder(vao);

    coordsVBO.data(sizeof(cubeCoords), cubeCoords);
    VAO::vertexAttribPointer("vertexCoord", coordsVBO, 3, GL_FLOAT, false, 0, 0);
    VAO::enableVertexAttribArray("vertexCoord");

    indicesVBO.data(sizeof(cubeIndices), cubeIndices);
}

CubeModel::~CubeModel()
{
}

CubeModel *CubeModel::instance()
{
    if (!s_instance)
        s_instance = new CubeModel();
    return s_instance;
}

void CubeModel::render()
{
    vao.bind();

    glDrawElements(GL_TRIANGLES, sizeof(cubeIndices)/3*sizeof(float), GL_UNSIGNED_SHORT, (GLvoid*) 0);
}

/////////////////////////////////////////////////////////////////////////////
// Cube
/////////////////////////////////////////////////////////////////////////////

Cube::Cube()
{
}

void Cube::prepare()
{
    (void) CubeModel::instance();
}

void Cube::render()
{
    CubeModel::instance()->render();
}
<commit_msg>Used TexturedVertex to specify cube vertices.<commit_after>#include "cube.hpp"
#include "vertex_format.hpp"

#include <cstddef>

using namespace plush;

const glm::vec3 LEFT_BOTTOM_FRONT (-.5f, -.5f, .5f);
const glm::vec3 RIGHT_BOTTOM_FRONT( .5f, -.5f, .5f);
const glm::vec3 RIGHT_TOP_FRONT   ( .5f,  .5f, .5f);
const glm::vec3 LEFT_TOP_FRONT    (-.5f,  .5f, .5f);
const glm::vec3 LEFT_BOTTOM_BACK  (-.5f, -.5f, -.5f);
const glm::vec3 RIGHT_BOTTOM_BACK ( .5f, -.5f, -.5f);
const glm::vec3 RIGHT_TOP_BACK    ( .5f,  .5f, -.5f);
const glm::vec3 LEFT_TOP_BACK     (-.5f,  .5f, -.5f);

const glm::vec3 NORMAL_LEFT     (-1.0f,  0.0f,  0.0f);
const glm::vec3 NORMAL_RIGHT    ( 1.0f,  0.0f,  0.0f);
const glm::vec3 NORMAL_UP       ( 0.0f,  1.0f,  0.0f);
const glm::vec3 NORMAL_DOWN     ( 0.0f, -1.0f,  0.0f);
const glm::vec3 NORMAL_FRONT    ( 0.0f,  0.0f,  1.0f);
const glm::vec3 NORMAL_BACK     ( 0.0f,  0.0f, -1.0f);

static const TexturedVertex cubeVertices[] = {

    // front side
    { LEFT_BOTTOM_FRONT,  NORMAL_FRONT, glm::vec2(0.0f, 0.0f), },
    { RIGHT_BOTTOM_FRONT, NORMAL_FRONT, glm::vec2(0.0f, 1.0f), },
    { RIGHT_TOP_FRONT,    NORMAL_FRONT, glm::vec2(1.0f, 1.0f), },
    { LEFT_TOP_FRONT,     NORMAL_FRONT, glm::vec2(1.0f, 1.0f), },

    // back side
    { LEFT_BOTTOM_BACK,   NORMAL_BACK,  glm::vec2(0.0f, 0.0f), },
    { RIGHT_BOTTOM_BACK,  NORMAL_BACK,  glm::vec2(0.0f, 0.0f), },
    { RIGHT_TOP_BACK,     NORMAL_BACK,  glm::vec2(0.0f, 0.0f), },
    { LEFT_TOP_BACK,      NORMAL_BACK,  glm::vec2(0.0f, 0.0f), },

    // left side
    { LEFT_BOTTOM_FRONT,  NORMAL_LEFT, },
    { LEFT_BOTTOM_BACK,   NORMAL_LEFT, },
    { LEFT_TOP_BACK,      NORMAL_LEFT, },
    { LEFT_TOP_FRONT,     NORMAL_LEFT, },

    // right side
    { RIGHT_BOTTOM_FRONT, NORMAL_RIGHT, },
    { RIGHT_BOTTOM_BACK,  NORMAL_RIGHT, },
    { RIGHT_TOP_BACK,     NORMAL_RIGHT, },
    { RIGHT_TOP_FRONT,    NORMAL_RIGHT, },

    // bottom side
    { LEFT_BOTTOM_FRONT,  NORMAL_DOWN, },
    { RIGHT_BOTTOM_FRONT, NORMAL_DOWN, },
    { RIGHT_BOTTOM_BACK,  NORMAL_DOWN, },
    { LEFT_BOTTOM_BACK,   NORMAL_DOWN, },

    // top side
    { LEFT_TOP_FRONT,     NORMAL_UP, },
    { RIGHT_TOP_FRONT,    NORMAL_UP, },
    { RIGHT_TOP_BACK,     NORMAL_UP, },
    { LEFT_TOP_BACK,      NORMAL_UP, },
};

static const short cubeIndices[] = {
    0, 1, 2, 0, 2, 3,                   // front side
    4, 5, 6, 4, 6, 7,                   // back side
    8, 9, 10, 8, 10, 11,                // left side
    12, 13, 14, 12, 14, 15,             // right side
    16, 17, 18, 16, 18, 19,             // bottom side
    20, 21, 22, 20, 22, 23,             // top side
};

/////////////////////////////////////////////////////////////////////////////
// CubeModel
/////////////////////////////////////////////////////////////////////////////

CubeModel *CubeModel::s_instance = nullptr;

CubeModel::CubeModel()
    : coordsVBO(GL_STATIC_DRAW), indicesVBO(GL_STATIC_DRAW)
{
    VAOBinder vaoBinder(vao);

    coordsVBO.data(sizeof(cubeVertices), cubeVertices);
    VAO::vertexAttribPointer("vertexCoord", coordsVBO, 3, GL_FLOAT, false, sizeof(TexturedVertex), offsetof(TexturedVertex, coord));
    VAO::enableVertexAttribArray("vertexCoord");

    indicesVBO.data(sizeof(cubeIndices), cubeIndices);
}

CubeModel::~CubeModel()
{
}

CubeModel *CubeModel::instance()
{
    if (!s_instance)
        s_instance = new CubeModel();
    return s_instance;
}

void CubeModel::render()
{
    vao.bind();

    glDrawElements(GL_TRIANGLES, sizeof(cubeIndices)/3*sizeof(float), GL_UNSIGNED_SHORT, (GLvoid*) 0);
}

/////////////////////////////////////////////////////////////////////////////
// Cube
/////////////////////////////////////////////////////////////////////////////

Cube::Cube()
{
}

void Cube::prepare()
{
    (void) CubeModel::instance();
}

void Cube::render()
{
    CubeModel::instance()->render();
}
<|endoftext|>


<commit_before>#include "json.hh"
#include "error.hh"
#include "logging.hh"
#include <boost/lexical_cast.hpp>
#include <sstream>
#include <deque>

namespace ten {
using namespace std;

extern "C" {
    static int ostream_json_dump_callback(const char *buffer, size_t size, void *osptr) {
        ostream *o = (ostream *)osptr;
        o->write(buffer, size);
        return 0;
    }
}

ostream & operator << (ostream &o, const json_t *j) {
    if (j)
        json_dump_callback(j, ostream_json_dump_callback, &o, JSON_ENCODE_ANY);
    return o;
}

void json::load(const string &s, unsigned flags) {
    load(s.data(), s.size(), flags);
}
void json::load(const char *s, size_t len, unsigned flags) {
    json_error_t err;
    json_ptr p(json_loadb(s, len, flags, &err), json_take);
    if (!p)
        throw errorx("%s", err.text);
    _p = move(p);
}

string json::dump(unsigned flags) {
    ostringstream ss;
    ss << _p;
    return ss.str();
}

// simple visit of all objects

void json::visit(const json::visitor_func_t &visitor) {
    if (is_object()) {
        for (auto kv : obj()) {
            if (!visitor(get(), kv.first, kv.second.get()))
                return;
            json(kv.second).visit(visitor);
        }
    }
    else if (is_array()) {
        for (auto j : arr()) {
            json(j).visit(visitor);
        }
    }
}

// for debugging
static ostream & operator << (ostream &o, const vector<string> &v) {
    for (size_t i = 0; i < v.size(); ++i) {
        if (i) o << " ";
        o << v[i];
    }
    return o;
}

static void add_result(json &result, json r) {
    if (r.is_array())
        result.aconcat(r);
    else
        result.apush(r);
}

static bool next_path_token(const string &path, size_t &i, string &tok) {
    size_t start = i;
    bool inquotes = false;
    while (i < path.size()) {
        switch (path[i])  {
        case '/':
        case '*':
        case '[':
        case ']':
        case ':':
        case ',':
        case '=':
            if (!inquotes)
                goto done;
            break;
        case '"':
            if (inquotes) {
                ++i;
                goto done;
            }
            inquotes = true;
            break;
        }
        ++i;
    }
done:
    if (start == i) ++i;
    tok.assign(path.substr(start, i - start));
    VLOG(5) << "tok: " << tok;
    return !tok.empty();
}

static void recursive_elements(json root, json &result, const string &match) {
    if (root.is_object()) {
        for (auto kv : root.obj()) {
            if (kv.first == match)
                add_result(result, kv.second);
            recursive_elements(json(kv.second), result, match);
        }
    }
    else if (root.is_array()) {
        for (auto el : root.arr())
            recursive_elements(el, result, match);
    }
}

static void match_node(json root, json &result, const string &match) {
    if (root.is_object()) {
        if (match == "*") {
            for (auto kv : root.obj())
                add_result(result, kv.second);
        }
        else {
            add_result(result, root[match]);
        }
    }
    else if (root.is_array()) {
        for (auto r : root.arr())
            match_node(r, result, match);
    }
}

static void select_node(json &result, deque<string> &tokens) {
    tokens.pop_front(); // remove '/'
    if (tokens.front() == "/") {
        // recursive decent!
        tokens.pop_front();
        string match = tokens.front();
        tokens.pop_front();
        json tmp(json::array());
        recursive_elements(result, tmp, match);
        result = tmp;
    } else {
        string match = tokens.front();
        if (match == "[") return;
        tokens.pop_front();
        json tmp(json::array());
        match_node(result, tmp, match);
        result = (tmp.asize() == 1) ? tmp(0) : tmp;
    }
}

static void slice_op(json &result, deque<string> &tokens) {
    tokens.pop_front();
    vector<string> args;
    while (!tokens.empty() && tokens.front() != "]") {
        args.push_back(tokens.front());
        tokens.pop_front();
    }
    if (tokens.empty())
        throw errorx("path query missing ]");
    tokens.pop_front(); // pop ']'

    DVLOG(5) << "args: " << args;
    if (args.size() == 1) {
        try {
            size_t index = boost::lexical_cast<size_t>(args.front());
            result = result(index);
        } catch (boost::bad_lexical_cast &e) {
            string key = args.front();
            auto tmp(json::array());
            for (auto r : result.arr()) {
                if (r[key])
                    add_result(tmp, r);
            }
            result = tmp;
        }
    } else if (args.size() == 3) {
        string op = args[1];
        if (op == ":") {
            ssize_t start = boost::lexical_cast<ssize_t>(args[0]);
            ssize_t end = boost::lexical_cast<ssize_t>(args[2]);
        }
        else if (op == "=") {
            string key = args[0];
            json filter(args[2]);
            DVLOG(5) << "filter: " << filter;
            json tmp(json::array());
            for (auto r : result.arr()) {
                if (r[key] == filter)
                    add_result(tmp, r);
            }
            result = tmp;
        }
    }
}

json json::path(const string &path) {
    size_t i = 0;
    string tok;
    deque<string> tokens;
    while (next_path_token(path, i, tok))
        tokens.push_back(tok);

    json result = *this;
    while (!tokens.empty()) {
        if (tokens.front() == "/") {
            // select current node
            select_node(result, tokens);
        }
        else if (tokens.front() == "*") {
            tokens.pop_front();
            if (result.is_object()) {
                auto tmp(json::array());
                for (auto kv : result.obj())
                    tmp.apush(kv.second);
                result = tmp;
            }
        }
        else if (tokens.front() == "[") {
            slice_op(result, tokens);
        }
    }
    return result;
}

} // TS
<commit_msg>add missing json::load overload<commit_after>#include "json.hh"
#include "error.hh"
#include "logging.hh"
#include <boost/lexical_cast.hpp>
#include <sstream>
#include <deque>

namespace ten {
using namespace std;

extern "C" {
    static int ostream_json_dump_callback(const char *buffer, size_t size, void *osptr) {
        ostream *o = (ostream *)osptr;
        o->write(buffer, size);
        return 0;
    }
}

ostream & operator << (ostream &o, const json_t *j) {
    if (j)
        json_dump_callback(j, ostream_json_dump_callback, &o, JSON_ENCODE_ANY);
    return o;
}

void json::load(const string &s, unsigned flags) {
    load(s.data(), s.size(), flags);
}
void json::load(const char *s, unsigned flags) {
    load(s, strlen(s), flags);
}
void json::load(const char *s, size_t len, unsigned flags) {
    json_error_t err;
    json_ptr p(json_loadb(s, len, flags, &err), json_take);
    if (!p)
        throw errorx("%s", err.text);
    _p = move(p);
}

string json::dump(unsigned flags) {
    ostringstream ss;
    ss << _p;
    return ss.str();
}

// simple visit of all objects

void json::visit(const json::visitor_func_t &visitor) {
    if (is_object()) {
        for (auto kv : obj()) {
            if (!visitor(get(), kv.first, kv.second.get()))
                return;
            json(kv.second).visit(visitor);
        }
    }
    else if (is_array()) {
        for (auto j : arr()) {
            json(j).visit(visitor);
        }
    }
}

// for debugging
static ostream & operator << (ostream &o, const vector<string> &v) {
    for (size_t i = 0; i < v.size(); ++i) {
        if (i) o << " ";
        o << v[i];
    }
    return o;
}

static void add_result(json &result, json r) {
    if (r.is_array())
        result.aconcat(r);
    else
        result.apush(r);
}

static bool next_path_token(const string &path, size_t &i, string &tok) {
    size_t start = i;
    bool inquotes = false;
    while (i < path.size()) {
        switch (path[i])  {
        case '/':
        case '*':
        case '[':
        case ']':
        case ':':
        case ',':
        case '=':
            if (!inquotes)
                goto done;
            break;
        case '"':
            if (inquotes) {
                ++i;
                goto done;
            }
            inquotes = true;
            break;
        }
        ++i;
    }
done:
    if (start == i) ++i;
    tok.assign(path.substr(start, i - start));
    VLOG(5) << "tok: " << tok;
    return !tok.empty();
}

static void recursive_elements(json root, json &result, const string &match) {
    if (root.is_object()) {
        for (auto kv : root.obj()) {
            if (kv.first == match)
                add_result(result, kv.second);
            recursive_elements(json(kv.second), result, match);
        }
    }
    else if (root.is_array()) {
        for (auto el : root.arr())
            recursive_elements(el, result, match);
    }
}

static void match_node(json root, json &result, const string &match) {
    if (root.is_object()) {
        if (match == "*") {
            for (auto kv : root.obj())
                add_result(result, kv.second);
        }
        else {
            add_result(result, root[match]);
        }
    }
    else if (root.is_array()) {
        for (auto r : root.arr())
            match_node(r, result, match);
    }
}

static void select_node(json &result, deque<string> &tokens) {
    tokens.pop_front(); // remove '/'
    if (tokens.front() == "/") {
        // recursive decent!
        tokens.pop_front();
        string match = tokens.front();
        tokens.pop_front();
        json tmp(json::array());
        recursive_elements(result, tmp, match);
        result = tmp;
    } else {
        string match = tokens.front();
        if (match == "[") return;
        tokens.pop_front();
        json tmp(json::array());
        match_node(result, tmp, match);
        result = (tmp.asize() == 1) ? tmp(0) : tmp;
    }
}

static void slice_op(json &result, deque<string> &tokens) {
    tokens.pop_front();
    vector<string> args;
    while (!tokens.empty() && tokens.front() != "]") {
        args.push_back(tokens.front());
        tokens.pop_front();
    }
    if (tokens.empty())
        throw errorx("path query missing ]");
    tokens.pop_front(); // pop ']'

    DVLOG(5) << "args: " << args;
    if (args.size() == 1) {
        try {
            size_t index = boost::lexical_cast<size_t>(args.front());
            result = result(index);
        } catch (boost::bad_lexical_cast &e) {
            string key = args.front();
            auto tmp(json::array());
            for (auto r : result.arr()) {
                if (r[key])
                    add_result(tmp, r);
            }
            result = tmp;
        }
    } else if (args.size() == 3) {
        string op = args[1];
        if (op == ":") {
            ssize_t start = boost::lexical_cast<ssize_t>(args[0]);
            ssize_t end = boost::lexical_cast<ssize_t>(args[2]);
        }
        else if (op == "=") {
            string key = args[0];
            json filter(args[2]);
            DVLOG(5) << "filter: " << filter;
            json tmp(json::array());
            for (auto r : result.arr()) {
                if (r[key] == filter)
                    add_result(tmp, r);
            }
            result = tmp;
        }
    }
}

json json::path(const string &path) {
    size_t i = 0;
    string tok;
    deque<string> tokens;
    while (next_path_token(path, i, tok))
        tokens.push_back(tok);

    json result = *this;
    while (!tokens.empty()) {
        if (tokens.front() == "/") {
            // select current node
            select_node(result, tokens);
        }
        else if (tokens.front() == "*") {
            tokens.pop_front();
            if (result.is_object()) {
                auto tmp(json::array());
                for (auto kv : result.obj())
                    tmp.apush(kv.second);
                result = tmp;
            }
        }
        else if (tokens.front() == "[") {
            slice_op(result, tokens);
        }
    }
    return result;
}

} // TS
<|endoftext|>


<commit_before>//===- PowerPCRegisterInfo.cpp - PowerPC Register Information ---*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the PowerPC implementation of the MRegisterInfo class.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "reginfo"
#include "PowerPC.h"
#include "PowerPCRegisterInfo.h"
#include "PowerPCInstrBuilder.h"
#include "llvm/Constants.h"
#include "llvm/Type.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetMachineImpls.h"
#include "Support/CommandLine.h"
#include "Support/Debug.h"
#include "Support/STLExtras.h"
using namespace llvm;

PowerPCRegisterInfo::PowerPCRegisterInfo()
  : PowerPCGenRegisterInfo(PPC32::ADJCALLSTACKDOWN,
                           PPC32::ADJCALLSTACKUP) {}

static unsigned getIdx(const TargetRegisterClass *RC) {
  if (RC == PowerPC::GPRCRegisterClass) {
    switch (RC->getSize()) {
      default: assert(0 && "Invalid data size!");
      case 1:  return 0;
      case 2:  return 1;
      case 4:  return 2;
    }
  } else if (RC == PowerPC::FPRCRegisterClass) {
    switch (RC->getSize()) {
      default: assert(0 && "Invalid data size!");
      case 4:  return 3;
      case 8:  return 4;
    }
  }
  std::cerr << "Invalid register class to getIdx()!\n";
  abort();
}

int
PowerPCRegisterInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
                                         MachineBasicBlock::iterator MI,
                                         unsigned SrcReg, int FrameIdx,
                                         const TargetRegisterClass *RC) const {
  static const unsigned Opcode[] = {
    PPC32::STB, PPC32::STH, PPC32::STW, PPC32::STFS, PPC32::STFD
  };
  unsigned OC = Opcode[getIdx(RC)];
  MBB.insert(MI, addFrameReference(BuildMI(OC, 3).addReg(SrcReg),FrameIdx));
  return 1;
}

int PowerPCRegisterInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
                                          MachineBasicBlock::iterator MI,
                                          unsigned DestReg, int FrameIdx,
                                          const TargetRegisterClass *RC) const{
  static const unsigned Opcode[] = {
    PPC32::LBZ, PPC32::LHZ, PPC32::LWZ, PPC32::LFS, PPC32::LFD
  };
  unsigned OC = Opcode[getIdx(RC)];
  MBB.insert(MI, addFrameReference(BuildMI(OC, 2, DestReg), FrameIdx));
  return 1;
}

int PowerPCRegisterInfo::copyRegToReg(MachineBasicBlock &MBB,
                                      MachineBasicBlock::iterator MI,
                                      unsigned DestReg, unsigned SrcReg,
                                      const TargetRegisterClass *RC) const {
  MachineInstr *I;

  if (RC == PowerPC::GPRCRegisterClass) {
    I = BuildMI(PPC32::OR, 2, DestReg).addReg(SrcReg).addReg(SrcReg);
  } else if (RC == PowerPC::FPRCRegisterClass) {
    I = BuildMI(PPC32::FMR, 1, DestReg).addReg(SrcReg);
  } else {
    std::cerr << "Attempt to copy register that is not GPR or FPR";
    abort();
  }
  MBB.insert(MI, I);
  return 1;
}

//===----------------------------------------------------------------------===//
// Stack Frame Processing methods
//===----------------------------------------------------------------------===//

// hasFP - Return true if the specified function should have a dedicated frame
// pointer register.  This is true if the function has variable sized allocas or
// if frame pointer elimination is disabled.
//
static bool hasFP(MachineFunction &MF) {
  return NoFramePointerElim || MF.getFrameInfo()->hasVarSizedObjects();
}

void PowerPCRegisterInfo::
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
                              MachineBasicBlock::iterator I) const {
  if (hasFP(MF)) {
    // If we have a frame pointer, turn the adjcallstackdown instruction into a
    // 'sub r1, r1, <amt>' and the adjcallstackup instruction into
    // 'add r1, r1, <amt>'
    MachineInstr *Old = I;
    int Amount = Old->getOperand(0).getImmedValue();
    if (Amount != 0) {
      // We need to keep the stack aligned properly.  To do this, we round the
      // amount of space needed for the outgoing arguments up to the next
      // alignment boundary.
      unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment();
      Amount = (Amount+Align-1)/Align*Align;

      MachineInstr *New;
      if (Old->getOpcode() == PPC32::ADJCALLSTACKDOWN) {
        New = BuildMI(PPC32::ADDI, 2, PPC32::R1).addReg(PPC32::R1)
                .addSImm(-Amount);
      } else {
        assert(Old->getOpcode() == PPC32::ADJCALLSTACKUP);
        New = BuildMI(PPC32::ADDI, 2, PPC32::R1).addReg(PPC32::R1)
                .addSImm(Amount);
      }

      // Replace the pseudo instruction with a new instruction...
      MBB.insert(I, New);
    }
  }

  MBB.erase(I);
}

void
PowerPCRegisterInfo::eliminateFrameIndex(MachineFunction &MF,
                                         MachineBasicBlock::iterator II) const {
  unsigned i = 0;
  MachineInstr &MI = *II;
  while (!MI.getOperand(i).isFrameIndex()) {
    ++i;
    assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
  }

  int FrameIndex = MI.getOperand(i).getFrameIndex();

  // This must be part of a four operand memory reference.  Replace the
  // FrameIndex with base register with GPR1.
  MI.SetMachineOperandReg(i, PPC32::R1);

  // Take into account whether its an add or mem instruction
  if (i == 2) i--;

  // Now add the frame object offset to the offset from r1.
  int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) +
               MI.getOperand(i).getImmedValue()+4;

  if (!hasFP(MF))
    Offset += MF.getFrameInfo()->getStackSize();

  MI.SetMachineOperandConst(i, MachineOperand::MO_SignExtendedImmed, Offset);
  DEBUG(std::cerr << "offset = " << Offset << std::endl);
}

void
PowerPCRegisterInfo::processFunctionBeforeFrameFinalized(MachineFunction &MF)
  const {
  // Do Nothing
}

void PowerPCRegisterInfo::emitPrologue(MachineFunction &MF) const {
  MachineBasicBlock &MBB = MF.front();   // Prolog goes in entry BB
  MachineBasicBlock::iterator MBBI = MBB.begin();
  MachineFrameInfo *MFI = MF.getFrameInfo();
  MachineInstr *MI;

  // Get the number of bytes to allocate from the FrameInfo
  unsigned NumBytes = MFI->getStackSize();

  if (MFI->hasCalls()) {
    // When we have no frame pointer, we reserve argument space for call sites
    // in the function immediately on entry to the current function.  This
    // eliminates the need for add/sub brackets around call sites.
    //
    NumBytes += MFI->getMaxCallFrameSize();

    // Round the size to a multiple of the alignment (don't forget the 4 byte
    // offset though).
    unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment();
    NumBytes = ((NumBytes+4)+Align-1)/Align*Align - 4;

    // Store the incoming LR so it is preserved across calls
    MI = BuildMI(PPC32::MFLR, 0, PPC32::R0);
    MBB.insert(MBBI, MI);
    MI = BuildMI(PPC32::STW, 3).addReg(PPC32::R31).addSImm(-4)
           .addReg(PPC32::R1);
    MBB.insert(MBBI, MI);
    MI = BuildMI(PPC32::STW, 3).addReg(PPC32::R0).addSImm(8).addReg(PPC32::R1);
    MBB.insert(MBBI, MI);
  }

  // Update frame info to pretend that this is part of the stack...
  MFI->setStackSize(NumBytes);

  // adjust stack pointer: r1 -= numbytes
  if (NumBytes) {
    MI = BuildMI(PPC32::STWU, 2, PPC32::R1).addImm(-NumBytes).addReg(PPC32::R1);
    MBB.insert(MBBI, MI);
  }
}

void PowerPCRegisterInfo::emitEpilogue(MachineFunction &MF,
                                       MachineBasicBlock &MBB) const {
  const MachineFrameInfo *MFI = MF.getFrameInfo();
  MachineBasicBlock::iterator MBBI = prior(MBB.end());
  MachineInstr *MI;
  assert(MBBI->getOpcode() == PPC32::BLR &&
         "Can only insert epilog into returning blocks");

  // Get the number of bytes allocated from the FrameInfo...
  unsigned NumBytes = MFI->getStackSize();

  // Read old LR from stack into R0
  MI = BuildMI(PPC32::LWZ, 2, PPC32::R0).addSImm(8+NumBytes).addReg(PPC32::R1);
  MBB.insert(MBBI, MI);

  // Adjust stack pointer back: r1 += numbytes
  if (NumBytes) {
    MI = BuildMI(PPC32::ADDI, 2, PPC32::R1).addReg(PPC32::R1).addSImm(NumBytes);
    MBB.insert(MBBI, MI);
  }

  // If we have calls, restore the LR value before we branch to it
  if (MFI->hasCalls()) {
    MI = BuildMI(PPC32::MTLR, 1).addReg(PPC32::R0);
    MBB.insert(MBBI, MI);
    MI = BuildMI(PPC32::LWZ, 2, PPC32::R31).addSImm(-4).addReg(PPC32::R1);
    MBB.insert(MBBI, MI);
  }
}

#include "PowerPCGenRegisterInfo.inc"

const TargetRegisterClass*
PowerPCRegisterInfo::getRegClassForType(const Type* Ty) const {
  switch (Ty->getTypeID()) {
    case Type::LongTyID:
    case Type::ULongTyID: assert(0 && "Long values can't fit in registers!");
    default:              assert(0 && "Invalid type to getClass!");
    case Type::BoolTyID:
    case Type::SByteTyID:
    case Type::UByteTyID:
    case Type::ShortTyID:
    case Type::UShortTyID:
    case Type::IntTyID:
    case Type::UIntTyID:
    case Type::PointerTyID: return &GPRCInstance;

    case Type::FloatTyID:
    case Type::DoubleTyID: return &FPRCInstance;
  }
}

<commit_msg>Set up the prologue and epilogue to be more like the manual and GCC output.<commit_after>//===- PowerPCRegisterInfo.cpp - PowerPC Register Information ---*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the PowerPC implementation of the MRegisterInfo class.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "reginfo"
#include "PowerPC.h"
#include "PowerPCRegisterInfo.h"
#include "PowerPCInstrBuilder.h"
#include "llvm/Constants.h"
#include "llvm/Type.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetMachineImpls.h"
#include "Support/CommandLine.h"
#include "Support/Debug.h"
#include "Support/STLExtras.h"
using namespace llvm;

PowerPCRegisterInfo::PowerPCRegisterInfo()
  : PowerPCGenRegisterInfo(PPC32::ADJCALLSTACKDOWN,
                           PPC32::ADJCALLSTACKUP) {}

static unsigned getIdx(const TargetRegisterClass *RC) {
  if (RC == PowerPC::GPRCRegisterClass) {
    switch (RC->getSize()) {
      default: assert(0 && "Invalid data size!");
      case 1:  return 0;
      case 2:  return 1;
      case 4:  return 2;
    }
  } else if (RC == PowerPC::FPRCRegisterClass) {
    switch (RC->getSize()) {
      default: assert(0 && "Invalid data size!");
      case 4:  return 3;
      case 8:  return 4;
    }
  }
  std::cerr << "Invalid register class to getIdx()!\n";
  abort();
}

int
PowerPCRegisterInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
                                         MachineBasicBlock::iterator MI,
                                         unsigned SrcReg, int FrameIdx,
                                         const TargetRegisterClass *RC) const {
  static const unsigned Opcode[] = {
    PPC32::STB, PPC32::STH, PPC32::STW, PPC32::STFS, PPC32::STFD
  };
  unsigned OC = Opcode[getIdx(RC)];
  MBB.insert(MI, addFrameReference(BuildMI(OC, 3).addReg(SrcReg),FrameIdx));
  return 1;
}

int PowerPCRegisterInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
                                          MachineBasicBlock::iterator MI,
                                          unsigned DestReg, int FrameIdx,
                                          const TargetRegisterClass *RC) const{
  static const unsigned Opcode[] = {
    PPC32::LBZ, PPC32::LHZ, PPC32::LWZ, PPC32::LFS, PPC32::LFD
  };
  unsigned OC = Opcode[getIdx(RC)];
  MBB.insert(MI, addFrameReference(BuildMI(OC, 2, DestReg), FrameIdx));
  return 1;
}

int PowerPCRegisterInfo::copyRegToReg(MachineBasicBlock &MBB,
                                      MachineBasicBlock::iterator MI,
                                      unsigned DestReg, unsigned SrcReg,
                                      const TargetRegisterClass *RC) const {
  MachineInstr *I;

  if (RC == PowerPC::GPRCRegisterClass) {
    I = BuildMI(PPC32::OR, 2, DestReg).addReg(SrcReg).addReg(SrcReg);
  } else if (RC == PowerPC::FPRCRegisterClass) {
    I = BuildMI(PPC32::FMR, 1, DestReg).addReg(SrcReg);
  } else {
    std::cerr << "Attempt to copy register that is not GPR or FPR";
    abort();
  }
  MBB.insert(MI, I);
  return 1;
}

//===----------------------------------------------------------------------===//
// Stack Frame Processing methods
//===----------------------------------------------------------------------===//

// hasFP - Return true if the specified function should have a dedicated frame
// pointer register.  This is true if the function has variable sized allocas or
// if frame pointer elimination is disabled.
//
static bool hasFP(MachineFunction &MF) {
  return NoFramePointerElim || MF.getFrameInfo()->hasVarSizedObjects();
}

void PowerPCRegisterInfo::
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
                              MachineBasicBlock::iterator I) const {
  if (hasFP(MF)) {
    // If we have a frame pointer, turn the adjcallstackdown instruction into a
    // 'sub r1, r1, <amt>' and the adjcallstackup instruction into
    // 'add r1, r1, <amt>'
    MachineInstr *Old = I;
    int Amount = Old->getOperand(0).getImmedValue();
    if (Amount != 0) {
      // We need to keep the stack aligned properly.  To do this, we round the
      // amount of space needed for the outgoing arguments up to the next
      // alignment boundary.
      unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment();
      Amount = (Amount+Align-1)/Align*Align;

      MachineInstr *New;
      if (Old->getOpcode() == PPC32::ADJCALLSTACKDOWN) {
        New = BuildMI(PPC32::ADDI, 2, PPC32::R1).addReg(PPC32::R1)
                .addSImm(-Amount);
      } else {
        assert(Old->getOpcode() == PPC32::ADJCALLSTACKUP);
        New = BuildMI(PPC32::ADDI, 2, PPC32::R1).addReg(PPC32::R1)
                .addSImm(Amount);
      }

      // Replace the pseudo instruction with a new instruction...
      MBB.insert(I, New);
    }
  }

  MBB.erase(I);
}

void
PowerPCRegisterInfo::eliminateFrameIndex(MachineFunction &MF,
                                         MachineBasicBlock::iterator II) const {
  unsigned i = 0;
  MachineInstr &MI = *II;
  while (!MI.getOperand(i).isFrameIndex()) {
    ++i;
    assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
  }

  int FrameIndex = MI.getOperand(i).getFrameIndex();

  // This must be part of a four operand memory reference.  Replace the
  // FrameIndex with base register with GPR1.
  MI.SetMachineOperandReg(i, PPC32::R1);

  // Take into account whether its an add or mem instruction
  if (i == 2) i--;

  // Now add the frame object offset to the offset from r1.
  int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) +
               MI.getOperand(i).getImmedValue()+4;

  if (!hasFP(MF))
    Offset += MF.getFrameInfo()->getStackSize();

  MI.SetMachineOperandConst(i, MachineOperand::MO_SignExtendedImmed, Offset);
  DEBUG(std::cerr << "offset = " << Offset << std::endl);
}

void
PowerPCRegisterInfo::processFunctionBeforeFrameFinalized(MachineFunction &MF)
  const {
  // Do Nothing
}

void PowerPCRegisterInfo::emitPrologue(MachineFunction &MF) const {
  MachineBasicBlock &MBB = MF.front();   // Prolog goes in entry BB
  MachineBasicBlock::iterator MBBI = MBB.begin();
  MachineFrameInfo *MFI = MF.getFrameInfo();
  MachineInstr *MI;

  // Get the number of bytes to allocate from the FrameInfo
  unsigned NumBytes = MFI->getStackSize();

  if (MFI->hasCalls()) {
    // When we have no frame pointer, we reserve argument space for call sites
    // in the function immediately on entry to the current function.  This
    // eliminates the need for add/sub brackets around call sites.
    //
    NumBytes += MFI->getMaxCallFrameSize();

    // Round the size to a multiple of the alignment (don't forget the 4 byte
    // offset though).
    unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment();
    NumBytes = ((NumBytes+4)+Align-1)/Align*Align - 4;

    // Store the incoming LR so it is preserved across calls
    MI = BuildMI(PPC32::MFLR, 0, PPC32::R0);
    MBB.insert(MBBI, MI);
    MI = BuildMI(PPC32::STMW, 3).addReg(PPC32::R30).addSImm(-8)
           .addReg(PPC32::R1);
    MBB.insert(MBBI, MI);
    MI = BuildMI(PPC32::STW, 3).addReg(PPC32::R0).addSImm(8).addReg(PPC32::R1);
    MBB.insert(MBBI, MI);
  }

  // Update frame info to pretend that this is part of the stack...
  MFI->setStackSize(NumBytes);

  // adjust stack pointer: r1 -= numbytes
  if (NumBytes) {
    MI = BuildMI(PPC32::STWU, 2, PPC32::R1).addImm(-80).addReg(PPC32::R1);
    MBB.insert(MBBI, MI);
  }
}

void PowerPCRegisterInfo::emitEpilogue(MachineFunction &MF,
                                       MachineBasicBlock &MBB) const {
  const MachineFrameInfo *MFI = MF.getFrameInfo();
  MachineBasicBlock::iterator MBBI = prior(MBB.end());
  MachineInstr *MI;
  assert(MBBI->getOpcode() == PPC32::BLR &&
         "Can only insert epilog into returning blocks");

  // Get the number of bytes allocated from the FrameInfo...
  unsigned NumBytes = MFI->getStackSize();

  // Adjust stack pointer back
  MI = BuildMI(PPC32::LWZ, 2, PPC32::R1).addImm(0).addReg(PPC32::R1);
  MBB.insert(MBBI, MI);

  // If we have calls, restore the LR value before we branch to it
  if (MFI->hasCalls()) {
    // Read old LR from stack into R0
    MI = BuildMI(PPC32::LWZ, 2, PPC32::R0).addSImm(8).addReg(PPC32::R1);
    MBB.insert(MBBI, MI);
    MI = BuildMI(PPC32::MTLR, 1).addReg(PPC32::R0);
    MBB.insert(MBBI, MI);
    MI = BuildMI(PPC32::LMW, 2, PPC32::R30).addSImm(-8).addReg(PPC32::R1);
    MBB.insert(MBBI, MI);
  }
}

#include "PowerPCGenRegisterInfo.inc"

const TargetRegisterClass*
PowerPCRegisterInfo::getRegClassForType(const Type* Ty) const {
  switch (Ty->getTypeID()) {
    case Type::LongTyID:
    case Type::ULongTyID: assert(0 && "Long values can't fit in registers!");
    default:              assert(0 && "Invalid type to getClass!");
    case Type::BoolTyID:
    case Type::SByteTyID:
    case Type::UByteTyID:
    case Type::ShortTyID:
    case Type::UShortTyID:
    case Type::IntTyID:
    case Type::UIntTyID:
    case Type::PointerTyID: return &GPRCInstance;

    case Type::FloatTyID:
    case Type::DoubleTyID: return &FPRCInstance;
  }
}

<|endoftext|>