<commit_before>// Copyright 2016 AUV-IITK
#include <ros/ros.h>
#include <std_msgs/Float32.h>
#include <std_msgs/Float64.h>
#include <std_msgs/Int32.h>
#include <actionlib/server/simple_action_server.h>
#include <motion_commons/SidewardAction.h>
#include <dynamic_reconfigure/server.h>
#include <motion_sideward/pidConfig.h>
#include <string>
#define minPWM 121
#define maxPWM 140
using std::string;

typedef actionlib::SimpleActionServer<motion_commons::SidewardAction> Server;  // defining the Client type

float presentSidePosition = 0;
float previousSidePosition = 0;
float finalSidePosition, error, output;
bool initData = false;
int count = 0;

std_msgs::Int32 pwm;  // pwm to be send to arduino

// new inner class, to encapsulate the interaction with actionclient
class innerActionClass
{
private:
  ros::NodeHandle nh_;
  Server sidewardServer_;
  std::string action_name_;
  motion_commons::SidewardFeedback feedback_;
  motion_commons::SidewardResult result_;
  ros::Publisher PWM;
  float p, i, d;

public:
  // Constructor, called when new instance of class declared
  explicit innerActionClass(std::string name)
    :  // Defining the server, third argument is optional
    sidewardServer_(nh_, name, boost::bind(&innerActionClass::analysisCB, this, _1), false)
    , action_name_(name)
  {
    // Add preempt callback
    sidewardServer_.registerPreemptCallback(boost::bind(&innerActionClass::preemptCB, this));
    PWM = nh_.advertise<std_msgs::Int32>("/pwm/sideward", 1000);
    // Starting new Action Server
    sidewardServer_.start();
  }

  // default contructor
  ~innerActionClass(void)
  {
  }

  // callback for goal cancelled
  // Stop the bot
  void preemptCB(void)
  {
    pwm.data = 0;
    PWM.publish(pwm);
    ROS_INFO("pwm send to arduino %d", pwm.data);
    // this command cancels the previous goal
    // sidewardServer_.setPreempted();
  }

  // called when new goal recieved
  // Start motion and finish it, if not interupted
  void analysisCB(const motion_commons::SidewardGoalConstPtr goal)
  {
    ROS_INFO("Inside analysisCB");

    int loopRate = 10;
    ros::Rate loop_rate(loopRate);

    // waiting till we recieve the first value from Camera else it's useless to
    // to any calculations
    while (!initData)
    {
      ROS_INFO("Waiting to get first input from Camera");
      loop_rate.sleep();
    }

    if (goal->Goal == 1)
      finalSidePosition = 0;

    float derivative = 0, integral = 0, dt = 1.0 / loopRate;
    bool reached = false;

    pwm.data = 0;

    if (!sidewardServer_.isActive())
      return;

    while (!sidewardServer_.isPreemptRequested() && ros::ok() && count<10)
    {
      error = finalSidePosition - presentSidePosition;
      integral += (error * dt);
      derivative = (presentSidePosition - previousSidePosition) / dt;

      output = (p * error) + (i * integral) + (d * derivative);

      sidewardOutputPWMMapping(output);

      // this lower limit depends upon the bot itself, below these values of PWM
      // thrusters will not start
      if (mod(pwm.data) > maxPWM)
      {
        if (pwm.data < 0)
          pwm.data = -maxPWM;
        else
          pwm.data = maxPWM;
      }

      feedback_.DistanceRemaining = error;

      sidewardServer_.publishFeedback(feedback_);
      PWM.publish(pwm);
      ROS_INFO("pwm send to arduino %d", pwm.data);

      ros::spinOnce();
      loop_rate.sleep();

      if (error < 5 && error > -5)  // assuming that this angle is in degree
      {
        // write something to calculate the time we will wait for and check if
        // we are in the range of 5 degrees
        // we can also check that if we are in this range and the angular
        // velocity is also small then we can assume
        // that we are stable and we can now start moving
        reached = true;
        pwm.data = 0;
        PWM.publish(pwm);
        ROS_INFO("thrusters stopped");
        count++;
      }

      if (sidewardServer_.isPreemptRequested() || !ros::ok())
      {
        ROS_INFO("%s: Preempted", action_name_.c_str());
        // set the action state to preempted
        sidewardServer_.setPreempted();
        reached = false;
        break;
      }
    }

    if (reached)
    {
      result_.Result = reached;
      ROS_INFO("%s: Succeeded", action_name_.c_str());
      // set the action state to succeeded
      sidewardServer_.setSucceeded(result_);
    }
  }
  void sidewardOutputPWMMapping(float output)
  {
    float maxOutput = 200, minOutput = -200, scale;  // upper limit in terms of error ex. 100 cm of distance we will
                                                     // consider all distances > 100cm as 100cm

    scale = (maxPWM - minPWM) / (maxOutput - 0);
    float temp;
    float bias;
    if (output > 0)
      bias = minPWM;  // the minPWM;
    else
      bias = -minPWM;

    temp = output * scale + bias;
    pwm.data = static_cast<int>(temp);
  }
  int mod(int a)
  {
    if (a < 0)
      return -a;
    else
      return a;
  }
  void setPID(float new_p, float new_i, float new_d)
  {
    p = new_p;
    i = new_i;
    d = new_d;
  }
};
innerActionClass *object;

/// dynamic reconfig
void callback(motion_sideward::pidConfig &config, double level)
{
  ROS_INFO("Reconfigure Request: p= %f i= %f d=%f", config.p, config.i, config.d);
  object->setPID(config.p, config.i, config.d);
}

void distanceCb(std_msgs::Float64 msg)
{
  // this is used to set the final angle after getting the value of first intial
  // position
  if (initData == false)
  {
    presentSidePosition = msg.data;
    previousSidePosition = presentSidePosition;
    initData = true;
  }
  else
  {
    previousSidePosition = presentSidePosition;
    presentSidePosition = msg.data;
    // ROS_INFO("New angular postion %f", msg.data);
  }
}

int main(int argc, char **argv)
{
  ros::init(argc, argv, "sideward");

  ros::NodeHandle n;
  ros::Subscriber yDistance = n.subscribe<std_msgs::Float64>("yDistance", 1000, &distanceCb);

  ROS_INFO("Waiting for Goal");
  object = new innerActionClass(ros::this_node::getName());

  // register dynamic reconfig server.
  dynamic_reconfigure::Server<motion_sideward::pidConfig> server;
  dynamic_reconfigure::Server<motion_sideward::pidConfig>::CallbackType f;
  f = boost::bind(&callback, _1, _2);
  server.setCallback(f);

  ros::spin();
  return 0;
}
<commit_msg>roslint error fixed<commit_after>// Copyright 2016 AUV-IITK
#include <ros/ros.h>
#include <std_msgs/Float32.h>
#include <std_msgs/Float64.h>
#include <std_msgs/Int32.h>
#include <actionlib/server/simple_action_server.h>
#include <motion_commons/SidewardAction.h>
#include <dynamic_reconfigure/server.h>
#include <motion_sideward/pidConfig.h>
#include <string>
#define minPWM 121
#define maxPWM 140
using std::string;

typedef actionlib::SimpleActionServer<motion_commons::SidewardAction> Server;  // defining the Client type

float presentSidePosition = 0;
float previousSidePosition = 0;
float finalSidePosition, error, output;
bool initData = false;
int count = 0;

std_msgs::Int32 pwm;  // pwm to be send to arduino

// new inner class, to encapsulate the interaction with actionclient
class innerActionClass
{
private:
  ros::NodeHandle nh_;
  Server sidewardServer_;
  std::string action_name_;
  motion_commons::SidewardFeedback feedback_;
  motion_commons::SidewardResult result_;
  ros::Publisher PWM;
  float p, i, d;

public:
  // Constructor, called when new instance of class declared
  explicit innerActionClass(std::string name)
    :  // Defining the server, third argument is optional
    sidewardServer_(nh_, name, boost::bind(&innerActionClass::analysisCB, this, _1), false)
    , action_name_(name)
  {
    // Add preempt callback
    sidewardServer_.registerPreemptCallback(boost::bind(&innerActionClass::preemptCB, this));
    PWM = nh_.advertise<std_msgs::Int32>("/pwm/sideward", 1000);
    // Starting new Action Server
    sidewardServer_.start();
  }

  // default contructor
  ~innerActionClass(void)
  {
  }

  // callback for goal cancelled
  // Stop the bot
  void preemptCB(void)
  {
    pwm.data = 0;
    PWM.publish(pwm);
    ROS_INFO("pwm send to arduino %d", pwm.data);
    // this command cancels the previous goal
    // sidewardServer_.setPreempted();
  }

  // called when new goal recieved
  // Start motion and finish it, if not interupted
  void analysisCB(const motion_commons::SidewardGoalConstPtr goal)
  {
    ROS_INFO("Inside analysisCB");

    int loopRate = 10;
    ros::Rate loop_rate(loopRate);

    // waiting till we recieve the first value from Camera else it's useless to
    // to any calculations
    while (!initData)
    {
      ROS_INFO("Waiting to get first input from Camera");
      loop_rate.sleep();
    }

    if (goal->Goal == 1)
      finalSidePosition = 0;

    float derivative = 0, integral = 0, dt = 1.0 / loopRate;
    bool reached = false;

    pwm.data = 0;

    if (!sidewardServer_.isActive())
      return;

    while (!sidewardServer_.isPreemptRequested() && ros::ok() && count < 10)
    {
      error = finalSidePosition - presentSidePosition;
      integral += (error * dt);
      derivative = (presentSidePosition - previousSidePosition) / dt;

      output = (p * error) + (i * integral) + (d * derivative);

      sidewardOutputPWMMapping(output);

      // this lower limit depends upon the bot itself, below these values of PWM
      // thrusters will not start
      if (mod(pwm.data) > maxPWM)
      {
        if (pwm.data < 0)
          pwm.data = -maxPWM;
        else
          pwm.data = maxPWM;
      }

      feedback_.DistanceRemaining = error;

      sidewardServer_.publishFeedback(feedback_);
      PWM.publish(pwm);
      ROS_INFO("pwm send to arduino %d", pwm.data);

      ros::spinOnce();
      loop_rate.sleep();

      if (error < 5 && error > -5)  // assuming that this angle is in degree
      {
        // write something to calculate the time we will wait for and check if
        // we are in the range of 5 degrees
        // we can also check that if we are in this range and the angular
        // velocity is also small then we can assume
        // that we are stable and we can now start moving
        reached = true;
        pwm.data = 0;
        PWM.publish(pwm);
        ROS_INFO("thrusters stopped");
        count++;
      }

      if (sidewardServer_.isPreemptRequested() || !ros::ok())
      {
        ROS_INFO("%s: Preempted", action_name_.c_str());
        // set the action state to preempted
        sidewardServer_.setPreempted();
        reached = false;
        break;
      }
    }

    if (reached)
    {
      result_.Result = reached;
      ROS_INFO("%s: Succeeded", action_name_.c_str());
      // set the action state to succeeded
      sidewardServer_.setSucceeded(result_);
    }
  }
  void sidewardOutputPWMMapping(float output)
  {
    float maxOutput = 200, minOutput = -200, scale;  // upper limit in terms of error ex. 100 cm of distance we will
                                                     // consider all distances > 100cm as 100cm

    scale = (maxPWM - minPWM) / (maxOutput - 0);
    float temp;
    float bias;
    if (output > 0)
      bias = minPWM;  // the minPWM;
    else
      bias = -minPWM;

    temp = output * scale + bias;
    pwm.data = static_cast<int>(temp);
  }
  int mod(int a)
  {
    if (a < 0)
      return -a;
    else
      return a;
  }
  void setPID(float new_p, float new_i, float new_d)
  {
    p = new_p;
    i = new_i;
    d = new_d;
  }
};
innerActionClass *object;

/// dynamic reconfig
void callback(motion_sideward::pidConfig &config, double level)
{
  ROS_INFO("Reconfigure Request: p= %f i= %f d=%f", config.p, config.i, config.d);
  object->setPID(config.p, config.i, config.d);
}

void distanceCb(std_msgs::Float64 msg)
{
  // this is used to set the final angle after getting the value of first intial
  // position
  if (initData == false)
  {
    presentSidePosition = msg.data;
    previousSidePosition = presentSidePosition;
    initData = true;
  }
  else
  {
    previousSidePosition = presentSidePosition;
    presentSidePosition = msg.data;
    // ROS_INFO("New angular postion %f", msg.data);
  }
}

int main(int argc, char **argv)
{
  ros::init(argc, argv, "sideward");

  ros::NodeHandle n;
  ros::Subscriber yDistance = n.subscribe<std_msgs::Float64>("yDistance", 1000, &distanceCb);

  ROS_INFO("Waiting for Goal");
  object = new innerActionClass(ros::this_node::getName());

  // register dynamic reconfig server.
  dynamic_reconfigure::Server<motion_sideward::pidConfig> server;
  dynamic_reconfigure::Server<motion_sideward::pidConfig>::CallbackType f;
  f = boost::bind(&callback, _1, _2);
  server.setCallback(f);

  ros::spin();
  return 0;
}
<|endoftext|>


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

#include "chrome/common/importer/edge_importer_utils_win.h"

#include <Shlobj.h>

#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/win/registry.h"
#include "base/win/windows_version.h"
#include "chrome/common/importer/importer_test_registry_overrider_win.h"

namespace {

const base::char16 kEdgeSettingsMainKey[] = L"MicrosoftEdge\\Main";

const base::char16 kEdgePackageName[] =
    L"microsoft.microsoftedge_8wekyb3d8bbwe";

// We assume at the moment that the package name never changes for Edge.
base::string16 GetEdgePackageName() {
  return kEdgePackageName;
}

base::string16 GetEdgeRegistryKey(const base::string16& key_name) {
  base::string16 registry_key =
      L"Software\\Classes\\Local Settings\\"
      L"Software\\Microsoft\\Windows\\CurrentVersion\\AppContainer\\"
      L"Storage\\";
  registry_key += GetEdgePackageName();
  registry_key += L"\\";
  registry_key += key_name;
  return registry_key;
}

base::string16 GetPotentiallyOverridenEdgeKey(
    const base::string16& desired_key_path) {
  base::string16 test_registry_override(
      ImporterTestRegistryOverrider::GetTestRegistryOverride());
  return test_registry_override.empty() ? GetEdgeRegistryKey(desired_key_path)
                                        : test_registry_override;
}

}  // namespace

namespace importer {

base::string16 GetEdgeSettingsKey() {
  return GetPotentiallyOverridenEdgeKey(kEdgeSettingsMainKey);
}

base::FilePath GetEdgeDataFilePath() {
  wchar_t buffer[MAX_PATH];
  if (::SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT,
                        buffer) != S_OK)
    return base::FilePath();

  base::FilePath base_path(buffer);
  base::string16 rel_path = L"Packages\\";
  rel_path += GetEdgePackageName();
  rel_path += L"\\AC\\MicrosoftEdge\\User\\Default";
  return base_path.Append(rel_path);
}

bool IsEdgeFavoritesLegacyMode() {
  base::win::RegKey key(HKEY_CURRENT_USER, GetEdgeSettingsKey().c_str(),
                        KEY_READ);
  DWORD ese_enabled = 0;
  // Check whether Edge is using the new Extensible Store Engine (ESE) format
  // for its favorites.
  if (key.ReadValueDW(L"FavoritesESEEnabled", &ese_enabled) == ERROR_SUCCESS)
    return !ese_enabled;
  return true;
}

bool EdgeImporterCanImport() {
  base::File::Info file_info;
  if (base::win::GetVersion() < base::win::VERSION_WIN10)
    return false;
  return base::GetFileInfo(GetEdgeDataFilePath(), &file_info) &&
         file_info.is_directory;
}

}  // namespace importer
<commit_msg>Fix egde legacy mode detection<commit_after>// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/common/importer/edge_importer_utils_win.h"

#include <Shlobj.h>

#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/win/registry.h"
#include "base/win/windows_version.h"
#include "chrome/common/importer/importer_test_registry_overrider_win.h"

namespace {

const base::char16 kEdgeSettingsMainKey[] = L"MicrosoftEdge\\Main";

const base::char16 kEdgePackageName[] =
    L"microsoft.microsoftedge_8wekyb3d8bbwe";

// We assume at the moment that the package name never changes for Edge.
base::string16 GetEdgePackageName() {
  return kEdgePackageName;
}

base::string16 GetEdgeRegistryKey(const base::string16& key_name) {
  base::string16 registry_key =
      L"Software\\Classes\\Local Settings\\"
      L"Software\\Microsoft\\Windows\\CurrentVersion\\AppContainer\\"
      L"Storage\\";
  registry_key += GetEdgePackageName();
  registry_key += L"\\";
  registry_key += key_name;
  return registry_key;
}

base::string16 GetPotentiallyOverridenEdgeKey(
    const base::string16& desired_key_path) {
  base::string16 test_registry_override(
      ImporterTestRegistryOverrider::GetTestRegistryOverride());
  return test_registry_override.empty() ? GetEdgeRegistryKey(desired_key_path)
                                        : test_registry_override;
}

}  // namespace

namespace importer {

base::string16 GetEdgeSettingsKey() {
  return GetPotentiallyOverridenEdgeKey(kEdgeSettingsMainKey);
}

base::FilePath GetEdgeDataFilePath() {
  wchar_t buffer[MAX_PATH];
  if (::SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT,
                        buffer) != S_OK)
    return base::FilePath();

  base::FilePath base_path(buffer);
  base::string16 rel_path = L"Packages\\";
  rel_path += GetEdgePackageName();
  rel_path += L"\\AC\\MicrosoftEdge\\User\\Default";
  return base_path.Append(rel_path);
}

bool IsEdgeFavoritesLegacyMode() {
  base::win::RegKey key(HKEY_CURRENT_USER, GetEdgeSettingsKey().c_str(),
                        KEY_READ);
  DWORD ese_enabled = 0;
  // Check whether Edge is using the new Extensible Store Engine (ESE) format
  // for its favorites.
  if (key.ReadValueDW(L"FavoritesESEEnabled", &ese_enabled) == ERROR_SUCCESS)
    return !ese_enabled;
  // No value to read means not legacy mode
  return false;
}

bool EdgeImporterCanImport() {
  base::File::Info file_info;
  if (base::win::GetVersion() < base::win::VERSION_WIN10)
    return false;
  return base::GetFileInfo(GetEdgeDataFilePath(), &file_info) &&
         file_info.is_directory;
}

}  // namespace importer
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: dbmetadata.hxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: vg $ $Date: 2008-01-29 08:37:36 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef CONNECTIVITY_INC_CONNECTIVITY_DBMETADATA_HXX
#define CONNECTIVITY_INC_CONNECTIVITY_DBMETADATA_HXX

/** === begin UNO includes === **/
#ifndef _COM_SUN_STAR_SDBC_XCONNECTION_HPP_
#include <com/sun/star/sdbc/XConnection.hpp>
#endif
/** === end UNO includes === **/

#include <memory>

//........................................................................
namespace dbtools
{
//........................................................................

    //====================================================================
    //= DatabaseMetaData
    //====================================================================
    struct DatabaseMetaData_Impl;
    /** encapsulates meta data about a database/connection which cannot be obtained
        from the usual XDatabaseMetaData result set.

        Meta data perhaps isn't really the right term ... Some of the methods
        in this class involved heuristics, some are just a convenient wrapper
        around more complex ways to obtain the same information.

        @todo
            Once CWS dba30 is integrated, we could easily add all the meta data
            which is part of the "Info" property of a data source.
    */
    class DatabaseMetaData
    {
    private:
        ::std::auto_ptr< DatabaseMetaData_Impl >    m_pImpl;

    public:
        DatabaseMetaData();
        /** constructs a DatabaseMetaData instance
            @param  _rxConnection
                is the connection whose meta data you're interested in.
                Note that some of the information provided by this class can only be obtained
                if this connection denotes an application-level connection, i.e. supports
                the com.sun.star.sdb.Connection service.

            @throws ::com::sun::star::lang::IllegalArgumentException
                if the given connection is not <NULL/>, but the XDatabaseMetaData provided by it
                are <NULL/>
            @throws ::com::sun::star::sdbc::SQLException
                if obtaining the meta data from the connection throws an SQLException
            @throws ::com::sun::star::uno::RuntimeException
                if obtaining the meta data from the connection throws an RuntimeException
        */
        DatabaseMetaData(
            const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _connection );
        DatabaseMetaData( const DatabaseMetaData& _copyFrom );
        DatabaseMetaData& operator=( const DatabaseMetaData& _copyFrom );

        ~DatabaseMetaData();

    public:
        /** determines whether or not the instances is based on a valid connection

            As long as this method returns true<TRUE/>, you should expect all other
            methods throwing an SQLException when called.
        */
        bool    isConnected() const;

        /** resets the instance so that it's based on a new connection
        */
        inline  void    reset( const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _connection )
        {
            *this = DatabaseMetaData( _connection );
        }

        /// wraps XDatabaseMetaData::getIdentifierQuoteString
        const ::rtl::OUString&  getIdentifierQuoteString() const;

        /// wraps XDatabaseMetaData::getCatalogSeparator
        const ::rtl::OUString&  getCatalogSeparator() const;

        /** determines whether the database supports sub queries in the FROM part
            of a SELECT clause are supported.
            @throws ::com::sun::star::sdbc::SQLException
                with SQLState 08003 (connection does not exist) if the instances was
                default-constructed and does not have a connection, yet.
        */
        bool supportsSubqueriesInFrom() const;

        /** determines whether names in the database should be restricted to SQL-92 identifiers

            Effectively, this method checks the EnableSQL92Check property of the data source settings,
            if present.
        */
        bool restrictIdentifiersToSQL92() const;

        /** determines whether when generating SQL statements, an AS keyword should be generated
            before a correlation name.

            E.g., it determines whether SELECT * FROM table AS correlation_name or
            SELECT * FROM table correlation_name is generated.
        */
        bool generateASBeforeCorrelationName() const;
        bool shouldEscapeDateTime() const;

        /** determines the syntax to use for boolean comparison predicates

            @see ::com::sun::star::sdb::BooleanComparisonMode
        */
        sal_Int32
            getBooleanComparisonMode() const;

        /**
        *
        * \return <TRUE/> when relations are supported, otherwise <FALSE/>
        */
        bool supportsRelations() const;
    };

//........................................................................
} // namespace dbtools
//........................................................................

#endif // CONNECTIVITY_INC_CONNECTIVITY_DBMETADATA_HXX
<commit_msg>INTEGRATION: CWS changefileheader (1.7.22); FILE MERGED 2008/04/01 10:52:41 thb 1.7.22.2: #i85898# Stripping all external header guards 2008/03/28 15:23:15 rt 1.7.22.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: dbmetadata.hxx,v $
 * $Revision: 1.8 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef CONNECTIVITY_INC_CONNECTIVITY_DBMETADATA_HXX
#define CONNECTIVITY_INC_CONNECTIVITY_DBMETADATA_HXX

/** === begin UNO includes === **/
#include <com/sun/star/sdbc/XConnection.hpp>
/** === end UNO includes === **/

#include <memory>

//........................................................................
namespace dbtools
{
//........................................................................

    //====================================================================
    //= DatabaseMetaData
    //====================================================================
    struct DatabaseMetaData_Impl;
    /** encapsulates meta data about a database/connection which cannot be obtained
        from the usual XDatabaseMetaData result set.

        Meta data perhaps isn't really the right term ... Some of the methods
        in this class involved heuristics, some are just a convenient wrapper
        around more complex ways to obtain the same information.

        @todo
            Once CWS dba30 is integrated, we could easily add all the meta data
            which is part of the "Info" property of a data source.
    */
    class DatabaseMetaData
    {
    private:
        ::std::auto_ptr< DatabaseMetaData_Impl >    m_pImpl;

    public:
        DatabaseMetaData();
        /** constructs a DatabaseMetaData instance
            @param  _rxConnection
                is the connection whose meta data you're interested in.
                Note that some of the information provided by this class can only be obtained
                if this connection denotes an application-level connection, i.e. supports
                the com.sun.star.sdb.Connection service.

            @throws ::com::sun::star::lang::IllegalArgumentException
                if the given connection is not <NULL/>, but the XDatabaseMetaData provided by it
                are <NULL/>
            @throws ::com::sun::star::sdbc::SQLException
                if obtaining the meta data from the connection throws an SQLException
            @throws ::com::sun::star::uno::RuntimeException
                if obtaining the meta data from the connection throws an RuntimeException
        */
        DatabaseMetaData(
            const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _connection );
        DatabaseMetaData( const DatabaseMetaData& _copyFrom );
        DatabaseMetaData& operator=( const DatabaseMetaData& _copyFrom );

        ~DatabaseMetaData();

    public:
        /** determines whether or not the instances is based on a valid connection

            As long as this method returns true<TRUE/>, you should expect all other
            methods throwing an SQLException when called.
        */
        bool    isConnected() const;

        /** resets the instance so that it's based on a new connection
        */
        inline  void    reset( const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _connection )
        {
            *this = DatabaseMetaData( _connection );
        }

        /// wraps XDatabaseMetaData::getIdentifierQuoteString
        const ::rtl::OUString&  getIdentifierQuoteString() const;

        /// wraps XDatabaseMetaData::getCatalogSeparator
        const ::rtl::OUString&  getCatalogSeparator() const;

        /** determines whether the database supports sub queries in the FROM part
            of a SELECT clause are supported.
            @throws ::com::sun::star::sdbc::SQLException
                with SQLState 08003 (connection does not exist) if the instances was
                default-constructed and does not have a connection, yet.
        */
        bool supportsSubqueriesInFrom() const;

        /** determines whether names in the database should be restricted to SQL-92 identifiers

            Effectively, this method checks the EnableSQL92Check property of the data source settings,
            if present.
        */
        bool restrictIdentifiersToSQL92() const;

        /** determines whether when generating SQL statements, an AS keyword should be generated
            before a correlation name.

            E.g., it determines whether SELECT * FROM table AS correlation_name or
            SELECT * FROM table correlation_name is generated.
        */
        bool generateASBeforeCorrelationName() const;
        bool shouldEscapeDateTime() const;

        /** determines the syntax to use for boolean comparison predicates

            @see ::com::sun::star::sdb::BooleanComparisonMode
        */
        sal_Int32
            getBooleanComparisonMode() const;

        /**
        *
        * \return <TRUE/> when relations are supported, otherwise <FALSE/>
        */
        bool supportsRelations() const;
    };

//........................................................................
} // namespace dbtools
//........................................................................

#endif // CONNECTIVITY_INC_CONNECTIVITY_DBMETADATA_HXX
<|endoftext|>


<commit_before>#include "octave.h"
#include <stdio.h>

void sg_print_message(FILE* target, const char* str)
{
	fprintf(target, "%s", str);
}

void sg_print_warning(FILE* target, const char* str)
{
	if (target==stdout)
		::warning(str);
	else
		fprintf(target, "%s", str);
}

void sg_print_error(FILE* target, const char* str)
{
	fprintf(target, "%s", str);
}

void sg_cancel_computations(bool &delayed, bool &immediately)
{
}
<commit_msg>remove cruft<commit_after><|endoftext|>


<commit_before>/*
 *  This file is part of Poedit (https://poedit.net)
 *
 *  Copyright (C) 2014-2018 Vaclav Slavik
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a
 *  copy of this software and associated documentation files (the "Software"),
 *  to deal in the Software without restriction, including without limitation
 *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 *  and/or sell copies of the Software, and to permit persons to whom the
 *  Software is furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 *  DEALINGS IN THE SOFTWARE.
 *
 */

#include "syntaxhighlighter.h"

#include "catalog.h"
#include "str_helpers.h"

#include <unicode/uchar.h>

#include <regex>

namespace
{

class BasicSyntaxHighlighter : public SyntaxHighlighter
{
public:
    void Highlight(const std::wstring& s, const CallbackType& highlight) override
    {
        if (s.empty())
            return;

        const int length = int(s.length());

        for (auto i = s.begin(); i != s.end(); ++i)
        {
            if (!u_isblank(*i))
            {
                int wlen = int(i - s.begin());
                if (wlen)
                    highlight(0, wlen, LeadingWhitespace);
                break;
            }
        }

        for (auto i = s.rbegin(); i != s.rend(); ++i)
        {
            if (!u_isblank(*i))
            {
                int wlen = int(i - s.rbegin());
                if (wlen)
                    highlight(length - wlen, length, LeadingWhitespace);
                break;
            }
        }

        int blank_block_pos = -1;

        for (auto i = s.begin(); i != s.end(); ++i)
        {
            if (u_isblank(*i))
            {
                if (blank_block_pos == -1)
                    blank_block_pos = int(i - s.begin());
            }
            else if (blank_block_pos != -1)
            {
                int endpos = int(i - s.begin());
                if (endpos - blank_block_pos >= 2)
                    highlight(blank_block_pos, endpos, LeadingWhitespace);
                blank_block_pos = -1;
            }

            if (*i == '\\')
            {
                int pos = int(i - s.begin());
                if (++i == s.end())
                    break;
                // Note: this must match AnyTranslatableTextCtrl::EscapePlainText()
                switch (*i)
                {
                    case '0':
                    case 'n':
                    case 'r':
                    case 't':
                    case '\\':
                        highlight(pos, pos + 2, Escape);
                        break;
                    default:
                        break;
                }
            }
        }
    }
};

/// Highlighter that runs multiple sub-highlighters
class CompositeSyntaxHighlighter : public SyntaxHighlighter
{
public:
    void Add(std::shared_ptr<SyntaxHighlighter> h) { m_sub.push_back(h); }

    void Highlight(const std::wstring& s, const CallbackType& highlight) override
    {
        for (auto h : m_sub)
            h->Highlight(s, highlight);
    }

private:
    std::vector<std::shared_ptr<SyntaxHighlighter>> m_sub;
};

/// Match regular expressions for highlighting
class RegexSyntaxHighlighter : public SyntaxHighlighter
{
public:
    /// Ctor. Notice that @a re is a reference and must outlive the highlighter!
    RegexSyntaxHighlighter(std::wregex& re, TextKind kind) : m_re(re), m_kind(kind) {}

    void Highlight(const std::wstring& s, const CallbackType& highlight) override
    {
        std::wsregex_iterator next(s.begin(), s.end(), m_re);
        std::wsregex_iterator end;
        while (next != end)
        {
            auto match = *next++;
            if (match.empty())
                continue;
            int pos = static_cast<int>(match.position());
            highlight(pos, pos + static_cast<int>(match.length()), m_kind);
        }
    }

private:
    std::wregex& m_re;
    TextKind m_kind;
};

std::wregex RE_HTML_MARKUP(LR"((<\/?[a-zA-Z:-]+(\s+[-:\w]+(=([-:\w+]|"[^"]*"|'[^']*'))?)*\s*\/?>)|(&[^ ;]+;))",
                           std::regex_constants::ECMAScript | std::regex_constants::optimize);

// php-format per http://php.net/manual/en/function.sprintf.php plus positionals
std::wregex RE_PHP_FORMAT(LR"(%(\d+\$)?[-+]{0,2}([ 0]|'.)?-?\d*(\..?\d+)?[%bcdeEfFgGosuxX])",
                          std::regex_constants::ECMAScript | std::regex_constants::optimize);

// c-format per http://en.cppreference.com/w/cpp/io/c/fprintf,
//              http://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html
std::wregex RE_C_FORMAT(LR"(%(\d+\$)?[-+ #0]{0,5}(\d+|\*)?(\.(\d+|\*))?(hh|ll|[hljztL])?[%csdioxXufFeEaAgGnp])",
                        std::regex_constants::ECMAScript | std::regex_constants::optimize);

} // anonymous namespace

SyntaxHighlighterPtr SyntaxHighlighter::ForItem(const CatalogItem& item)
{
    auto formatFlag = item.GetFormatFlag();
    bool needsHTML = std::regex_search(str::to_wstring(item.GetString()), RE_HTML_MARKUP);

    static auto basic = std::make_shared<BasicSyntaxHighlighter>();
    if (!needsHTML && formatFlag.empty())
        return basic;

    auto all = std::make_shared<CompositeSyntaxHighlighter>();

    // HTML goes first, has lowest priority than special-purpose stuff like format strings:
    if (needsHTML)
    {
        static auto html = std::make_shared<RegexSyntaxHighlighter>(RE_HTML_MARKUP, TextKind::Markup);
        all->Add(html);
    }

    // TODO: more/all languages
    if (formatFlag == "php")
    {
        static auto php_format = std::make_shared<RegexSyntaxHighlighter>(RE_PHP_FORMAT, TextKind::Format);
        all->Add(php_format);
    }
    else if (formatFlag == "c")
    {
        static auto c_format = std::make_shared<RegexSyntaxHighlighter>(RE_C_FORMAT, TextKind::Format);
        all->Add(c_format);
    }

    // basic higlighting has highest priority, so should come last in the order:
    all->Add(basic);

    return all;
}
<commit_msg>Highlight syntax of common placeholders<commit_after>/*
 *  This file is part of Poedit (https://poedit.net)
 *
 *  Copyright (C) 2014-2018 Vaclav Slavik
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a
 *  copy of this software and associated documentation files (the "Software"),
 *  to deal in the Software without restriction, including without limitation
 *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 *  and/or sell copies of the Software, and to permit persons to whom the
 *  Software is furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 *  DEALINGS IN THE SOFTWARE.
 *
 */

#include "syntaxhighlighter.h"

#include "catalog.h"
#include "str_helpers.h"

#include <unicode/uchar.h>

#include <regex>

namespace
{

class BasicSyntaxHighlighter : public SyntaxHighlighter
{
public:
    void Highlight(const std::wstring& s, const CallbackType& highlight) override
    {
        if (s.empty())
            return;

        const int length = int(s.length());

        for (auto i = s.begin(); i != s.end(); ++i)
        {
            if (!u_isblank(*i))
            {
                int wlen = int(i - s.begin());
                if (wlen)
                    highlight(0, wlen, LeadingWhitespace);
                break;
            }
        }

        for (auto i = s.rbegin(); i != s.rend(); ++i)
        {
            if (!u_isblank(*i))
            {
                int wlen = int(i - s.rbegin());
                if (wlen)
                    highlight(length - wlen, length, LeadingWhitespace);
                break;
            }
        }

        int blank_block_pos = -1;

        for (auto i = s.begin(); i != s.end(); ++i)
        {
            if (u_isblank(*i))
            {
                if (blank_block_pos == -1)
                    blank_block_pos = int(i - s.begin());
            }
            else if (blank_block_pos != -1)
            {
                int endpos = int(i - s.begin());
                if (endpos - blank_block_pos >= 2)
                    highlight(blank_block_pos, endpos, LeadingWhitespace);
                blank_block_pos = -1;
            }

            if (*i == '\\')
            {
                int pos = int(i - s.begin());
                if (++i == s.end())
                    break;
                // Note: this must match AnyTranslatableTextCtrl::EscapePlainText()
                switch (*i)
                {
                    case '0':
                    case 'n':
                    case 'r':
                    case 't':
                    case '\\':
                        highlight(pos, pos + 2, Escape);
                        break;
                    default:
                        break;
                }
            }
        }
    }
};

/// Highlighter that runs multiple sub-highlighters
class CompositeSyntaxHighlighter : public SyntaxHighlighter
{
public:
    void Add(std::shared_ptr<SyntaxHighlighter> h) { m_sub.push_back(h); }

    void Highlight(const std::wstring& s, const CallbackType& highlight) override
    {
        for (auto h : m_sub)
            h->Highlight(s, highlight);
    }

private:
    std::vector<std::shared_ptr<SyntaxHighlighter>> m_sub;
};

/// Match regular expressions for highlighting
class RegexSyntaxHighlighter : public SyntaxHighlighter
{
public:
    /// Ctor. Notice that @a re is a reference and must outlive the highlighter!
    RegexSyntaxHighlighter(std::wregex& re, TextKind kind) : m_re(re), m_kind(kind) {}

    void Highlight(const std::wstring& s, const CallbackType& highlight) override
    {
        std::wsregex_iterator next(s.begin(), s.end(), m_re);
        std::wsregex_iterator end;
        while (next != end)
        {
            auto match = *next++;
            if (match.empty())
                continue;
            int pos = static_cast<int>(match.position());
            highlight(pos, pos + static_cast<int>(match.length()), m_kind);
        }
    }

private:
    std::wregex& m_re;
    TextKind m_kind;
};

std::wregex RE_HTML_MARKUP(LR"((<\/?[a-zA-Z:-]+(\s+[-:\w]+(=([-:\w+]|"[^"]*"|'[^']*'))?)*\s*\/?>)|(&[^ ;]+;))",
                           std::regex_constants::ECMAScript | std::regex_constants::optimize);

// php-format per http://php.net/manual/en/function.sprintf.php plus positionals
std::wregex RE_PHP_FORMAT(LR"(%(\d+\$)?[-+]{0,2}([ 0]|'.)?-?\d*(\..?\d+)?[%bcdeEfFgGosuxX])",
                          std::regex_constants::ECMAScript | std::regex_constants::optimize);

// c-format per http://en.cppreference.com/w/cpp/io/c/fprintf,
//              http://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html
std::wregex RE_C_FORMAT(LR"(%(\d+\$)?[-+ #0]{0,5}(\d+|\*)?(\.(\d+|\*))?(hh|ll|[hljztL])?[%csdioxXufFeEaAgGnp])",
                        std::regex_constants::ECMAScript | std::regex_constants::optimize);

// variables expansion for %foo% (Twig), {foo} and {{foo}}
std::wregex RE_COMMON_PLACEHOLDERS(LR"((%[0-9a-zA-Z_.-]+%)|(\{[0-9a-zA-Z_.-]+\})|(\{\{[0-9a-zA-Z_.-]+\}\}))",
                    std::regex_constants::ECMAScript | std::regex_constants::optimize);

} // anonymous namespace

SyntaxHighlighterPtr SyntaxHighlighter::ForItem(const CatalogItem& item)
{
    auto formatFlag = item.GetFormatFlag();
    bool needsHTML = std::regex_search(str::to_wstring(item.GetString()), RE_HTML_MARKUP);
    bool needsPlaceholders = std::regex_search(str::to_wstring(item.GetString()), RE_COMMON_PLACEHOLDERS);

    static auto basic = std::make_shared<BasicSyntaxHighlighter>();
    if (!needsHTML && !needsPlaceholders && formatFlag.empty())
        return basic;

    auto all = std::make_shared<CompositeSyntaxHighlighter>();

    // HTML goes first, has lowest priority than special-purpose stuff like format strings:
    if (needsHTML)
    {
        static auto html = std::make_shared<RegexSyntaxHighlighter>(RE_HTML_MARKUP, TextKind::Markup);
        all->Add(html);
    }

    if (needsPlaceholders)
    {
        // If no format specified, heuristically apply highlighting of common variable markers
        static auto placeholders = std::make_shared<RegexSyntaxHighlighter>(RE_COMMON_PLACEHOLDERS, TextKind::Format);
        all->Add(placeholders);
    }

    // TODO: more/all languages
    if (formatFlag == "php")
    {
        static auto php_format = std::make_shared<RegexSyntaxHighlighter>(RE_PHP_FORMAT, TextKind::Format);
        all->Add(php_format);
    }
    else if (formatFlag == "c")
    {
        static auto c_format = std::make_shared<RegexSyntaxHighlighter>(RE_C_FORMAT, TextKind::Format);
        all->Add(c_format);
    }

    // basic higlighting has highest priority, so should come last in the order:
    all->Add(basic);

    return all;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#define INCORRECT_PARAMS -1 // Ошибка: некорректное кол-во аргументов
#define INCORRECT_INPUT -2 // Ошибка: некорректное арифметическое выражение
#define ZERO_DIVISION -3 // Ошибка: деление на 0
#define OK 0

enum class Token {
    Invalid,
    Minus,
    Plus,
    Mul,
    Div,
    Number,
    End
};

/* Рекурсивная функция для разбиения выражения на слогаемые (или вычитаемое и частное),
 * либо на число, если text является простым выражением,
 * например, text = "123"
 */
double expr(const char*& text);
/* Рекурсивная функция для разбиения выражения на множители (или делимое и делитель),
 * либо на число, если text является простым выражением,
 * например, text = "123".
 * Аргумент типа size_t необходим для подсчёта числа знаков '/' в терме,
 * Т.к. возникаются трудности при вычислении такого выражения: 2 * 3 / 4
 * Алгоритм его воспринимает как: 2 * (3 / 4),
 * что не является корректным результатом исходного выражения.
 * Поэтому необходимо инвертировать каждый знак '*', вложенный в '/',
 * если степень вложенности нечётная.
 */
double term(const char*&, size_t = 0);
// Рекурсивная функция, преобразующая текст в целочисленное значение
double prim(const char*&);

// Функция для получения текущего токена из входной последовательности
Token getToken(const char*& text) {
    while (const auto ch = *text++) {
        switch (ch) {
            case ' ': continue;
            case '+': return Token::Plus;
            case '-': return Token::Minus;
            case '*': return Token::Mul;
            case '/': return Token::Div;
        }

        if (ch >= '0' && ch <= '9') {
            return Token::Number;
        }
        else return Token::Invalid;
    }
    return Token::End;
}

double expr(const char*& text) {
    auto leftOperand = term(text);
    auto token = getToken(text);
    if (Token::End != token) {
        return Token::Plus != token ? leftOperand - expr(text) : leftOperand + expr(text);
    }
    else return leftOperand;
}

double term(const char*& text, size_t cntEnter) {
    auto leftOperand = prim(text);
    auto token = getToken(text);
    if (Token::Mul == token || Token::Div == token) {
        /* Проверка на кол-во "вложенности" делений
         * Если бы не было данной проверки, то программа воспринимала бы такое выражение "2 / 3 * 4"
         * Как "2 / (3 * 4)" = 1 / 6, что != 8 / 3
         * Для борбы с этой проблемой было решено подсчитывать степень вложенности делений
         * Т.е. все знаки ('*' или '/'), которые внутри '/' будут инвертироваться
         */
        if ((cntEnter & 1) == 0) { // Проверка на нечётность
            return Token::Mul != token ? leftOperand / term(text, cntEnter + 1) : leftOperand * term(text, cntEnter);
        }
        else {
            return Token::Mul != token ? leftOperand * term(text, cntEnter) : leftOperand / term(text, cntEnter + 1);
        }
    }
    else {
        --text; // Когда getToken равняется '+' или '-', нам необходимо вернуть этот токен назад в text
        return leftOperand;
    }
}

double prim(const char*& text) {
    auto token = getToken(text);

    if (Token::Number == token) {
        int val = 0;
        /* Возвращаем символ, являющийся цифрой, во входную последовательность,
         * чтобы корректно преобразовать строку в число.
         */
        --text;
        // Преобазование строки в целочисленный тип
        for (auto ch = *text; ch >= '0' && ch <= '9'; ) {
            val = val * 10 + ch - '0';
            ch = *++text;
        }
        return val;
    }
    else return -prim(text);
}

int checkInput(const char* text) {
    char prevCh = ' '; // токен, считанный на предыдущей итерации
    size_t cntOperators = 0; // кол-во операторов, используемых послед-но
    while (prevCh = *text++) {
        if (prevCh != ' ')
            break;
    }
    if ((prevCh >= '0' && prevCh <= '9') || prevCh == '-') {
        if (prevCh == '-')
            cntOperators++;
        while (const auto ch = *text++) {
            switch (ch) {
                case ' ': continue;
                case '-':
                    if ((prevCh >= '0' && prevCh <= '9') || (prevCh == '-' && cntOperators <= 1)) {
                        prevCh = ch;
                        cntOperators++;
                        continue;
                    }
                    else return INCORRECT_INPUT;
                case '+':
                case '*':
                case '/':
                    if (prevCh >= '0' && prevCh <= '9') {
                        prevCh = ch;
                        cntOperators++;
                        continue;
                    }
                    else return INCORRECT_INPUT;
                case '0':
                    if (prevCh == '/')
                        return ZERO_DIVISION;
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                case '9':
                    if ((prevCh >= '0' && prevCh <= '9') || cntOperators > 0) {
                        cntOperators = 0;
                        prevCh = ch;
                        continue;
                    }
                    else return INCORRECT_INPUT;
                default:
                    return INCORRECT_INPUT;
            }
        }
        if (cntOperators > 0)
            return INCORRECT_INPUT;
    }
    else return INCORRECT_INPUT;
    return OK;
}

int main(int argc, char* argv[]) {
    if (argc != 2)
        return INCORRECT_PARAMS;
    auto checkCode = checkInput(argv[1]);
    if (checkCode != OK)
        return checkCode;
    // Оператор деления - вещественный
    const char* text = argv[1];
    std::cout << expr(text) << std::endl;
    return 0;
}<commit_msg>fix msu_work_02<commit_after>#include <iostream>
#include <string>
#define INCORRECT_PARAMS 1 // Ошибка: некорректное кол-во аргументов
#define INCORRECT_INPUT 2 // Ошибка: некорректное арифметическое выражение
#define ZERO_DIVISION 3 // Ошибка: деление на 0
#define OK 0

enum class Token {
    Invalid,
    Minus,
    Plus,
    Mul,
    Div,
    Number,
    End
};

/* Рекурсивная функция для разбиения выражения на слогаемые (или вычитаемое и частное),
 * либо на число, если text является простым выражением,
 * например, text = "123"
 */
double expr(const char*& text);
/* Рекурсивная функция для разбиения выражения на множители (или делимое и делитель),
 * либо на число, если text является простым выражением,
 * например, text = "123".
 * Аргумент типа size_t необходим для подсчёта числа знаков '/' в терме,
 * Т.к. возникаются трудности при вычислении такого выражения: 2 * 3 / 4
 * Алгоритм его воспринимает как: 2 * (3 / 4),
 * что не является корректным результатом исходного выражения.
 * Поэтому необходимо инвертировать каждый знак '*', вложенный в '/',
 * если степень вложенности нечётная.
 */
double term(const char*&, size_t = 0);
// Рекурсивная функция, преобразующая текст в целочисленное значение
double prim(const char*&);

// Функция для получения текущего токена из входной последовательности
Token getToken(const char*& text) {
    while (const auto ch = *text++) {
        switch (ch) {
            case ' ': continue;
            case '+': return Token::Plus;
            case '-': return Token::Minus;
            case '*': return Token::Mul;
            case '/': return Token::Div;
        }

        if (ch >= '0' && ch <= '9') {
            return Token::Number;
        }
        else return Token::Invalid;
    }
    return Token::End;
}

double expr(const char*& text) {
    auto leftOperand = term(text);
    auto token = getToken(text);
    if (Token::End != token) {
        return Token::Plus != token ? leftOperand - expr(text) : leftOperand + expr(text);
    }
    else return leftOperand;
}

double term(const char*& text, size_t cntEnter) {
    auto leftOperand = prim(text);
    auto token = getToken(text);
    if (Token::Mul == token || Token::Div == token) {
        /* Проверка на кол-во "вложенности" делений
         * Если бы не было данной проверки, то программа воспринимала бы такое выражение "2 / 3 * 4"
         * Как "2 / (3 * 4)" = 1 / 6, что != 8 / 3
         * Для борбы с этой проблемой было решено подсчитывать степень вложенности делений
         * Т.е. все знаки ('*' или '/'), которые внутри '/' будут инвертироваться
         */
        if ((cntEnter & 1) == 0) { // Проверка на нечётность
            return Token::Mul != token ? leftOperand / term(text, cntEnter + 1) : leftOperand * term(text, cntEnter);
        }
        else {
            return Token::Mul != token ? leftOperand * term(text, cntEnter) : leftOperand / term(text, cntEnter + 1);
        }
    }
    else {
        --text; // Когда getToken равняется '+' или '-', нам необходимо вернуть этот токен назад в text
        return leftOperand;
    }
}

double prim(const char*& text) {
    auto token = getToken(text);

    if (Token::Number == token) {
        int val = 0;
        /* Возвращаем символ, являющийся цифрой, во входную последовательность,
         * чтобы корректно преобразовать строку в число.
         */
        --text;
        // Преобазование строки в целочисленный тип
        for (auto ch = *text; ch >= '0' && ch <= '9'; ) {
            val = val * 10 + ch - '0';
            ch = *++text;
        }
        return val;
    }
    else return -prim(text);
}

int checkInput(const char* text) {
    char prevCh = *text++; // токен, считанный на предыдущей итерации
    size_t cntOperators = 0; // кол-во операторов, используемых послед-но
    while (prevCh) {
        if (prevCh != ' ')
            break;
        prevCh = *text++;
    }
    if ((prevCh >= '0' && prevCh <= '9') || prevCh == '-') {
        if (prevCh == '-')
            cntOperators++;
        while (const auto ch = *text++) {
            switch (ch) {
                case ' ': continue;
                case '-':
                    if ((prevCh >= '0' && prevCh <= '9') || cntOperators <= 1) {
                        prevCh = ch;
                        cntOperators++;
                        continue;
                    }
                    else return INCORRECT_INPUT;
                case '+':
                case '*':
                case '/':
                    if (prevCh >= '0' && prevCh <= '9') {
                        prevCh = ch;
                        cntOperators++;
                        continue;
                    }
                    else return INCORRECT_INPUT;
                case '0':
                    if (prevCh == '/')
                        return ZERO_DIVISION;
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                case '9':
                    if ((prevCh >= '0' && prevCh <= '9') || cntOperators > 0) {
                        cntOperators = 0;
                        prevCh = ch;
                        continue;
                    }
                    else return INCORRECT_INPUT;
                default:
                    return INCORRECT_INPUT;
            }
        }
        if (cntOperators > 0)
            return INCORRECT_INPUT;
    }
    else return INCORRECT_INPUT;
    return OK;
}

int main(int argc, char* argv[]) {
    if (argc != 2)
        return INCORRECT_PARAMS;
    auto checkCode = checkInput(argv[1]);
    if (checkCode != OK)
        return checkCode;
    // Оператор деления - вещественный
    const char* text = argv[1];
    std::cout << expr(text) << std::endl;
    return 0;
}<|endoftext|>


<commit_before>/*
 * Copyright (C) 2022-present ScyllaDB
 */

/*
 * SPDX-License-Identifier: AGPL-3.0-or-later
 */

#pragma once

#include <seastar/core/io_priority_class.hh>
#include "dht/i_partitioner.hh"
#include "query-request.hh"
#include "tracing/trace_state.hh"
#include "readers/flat_mutation_reader.hh"
#include "readers/flat_mutation_reader_v2.hh"

/// A partition_presence_checker quickly returns whether a key is known not to exist
/// in a data source (it may return false positives, but not false negatives).
enum class partition_presence_checker_result {
    definitely_doesnt_exist,
    maybe_exists
};
using partition_presence_checker = std::function<partition_presence_checker_result (const dht::decorated_key& key)>;

inline
partition_presence_checker make_default_partition_presence_checker() {
    return [] (const dht::decorated_key&) { return partition_presence_checker_result::maybe_exists; };
}

// mutation_source represents source of data in mutation form. The data source
// can be queried multiple times and in parallel. For each query it returns
// independent mutation_reader.
//
// The reader returns mutations having all the same schema, the one passed
// when invoking the source.
//
// When reading in reverse, a reverse schema has to be passed (compared to the
// table's schema), and a half-reverse (legacy) slice.
// See docs/design-notes/reverse-reads.md for more details.
// Partition-range forwarding is not yet supported in reverse mode.
class mutation_source {
    using partition_range = const dht::partition_range&;
    using io_priority = const io_priority_class&;
    using flat_reader_factory_type = std::function<flat_mutation_reader(schema_ptr,
                                                                        reader_permit,
                                                                        partition_range,
                                                                        const query::partition_slice&,
                                                                        io_priority,
                                                                        tracing::trace_state_ptr,
                                                                        streamed_mutation::forwarding,
                                                                        mutation_reader::forwarding)>;
    using flat_reader_v2_factory_type = std::function<flat_mutation_reader_v2(schema_ptr,
                                                                        reader_permit,
                                                                        partition_range,
                                                                        const query::partition_slice&,
                                                                        io_priority,
                                                                        tracing::trace_state_ptr,
                                                                        streamed_mutation::forwarding,
                                                                        mutation_reader::forwarding)>;
    // We could have our own version of std::function<> that is nothrow
    // move constructible and save some indirection and allocation.
    // Probably not worth the effort though.
    // Either _fn or _fn_v2 is engaged.
    lw_shared_ptr<flat_reader_factory_type> _fn;
    lw_shared_ptr<flat_reader_v2_factory_type> _fn_v2;
    lw_shared_ptr<std::function<partition_presence_checker()>> _presence_checker_factory;
private:
    static flat_mutation_reader_v2 upgrade_to_v2(flat_mutation_reader rd);
    mutation_source() = default;
    explicit operator bool() const { return bool(_fn) || bool(_fn_v2); }
    friend class optimized_optional<mutation_source>;
public:
    mutation_source(flat_reader_factory_type fn, std::function<partition_presence_checker()> pcf = [] { return make_default_partition_presence_checker(); })
        : _fn(make_lw_shared<flat_reader_factory_type>(std::move(fn)))
        , _presence_checker_factory(make_lw_shared<std::function<partition_presence_checker()>>(std::move(pcf)))
    { }

    mutation_source(flat_reader_v2_factory_type fn, std::function<partition_presence_checker()> pcf = [] { return make_default_partition_presence_checker(); })
        : _fn_v2(make_lw_shared<flat_reader_v2_factory_type>(std::move(fn)))
        , _presence_checker_factory(make_lw_shared<std::function<partition_presence_checker()>>(std::move(pcf)))
    { }

    // For sources which don't care about the mutation_reader::forwarding flag (always fast forwardable)
    mutation_source(std::function<flat_mutation_reader(schema_ptr, reader_permit, partition_range, const query::partition_slice&, io_priority,
                tracing::trace_state_ptr, streamed_mutation::forwarding)> fn)
        : mutation_source([fn = std::move(fn)] (schema_ptr s,
                    reader_permit permit,
                    partition_range range,
                    const query::partition_slice& slice,
                    io_priority pc,
                    tracing::trace_state_ptr tr,
                    streamed_mutation::forwarding fwd,
                    mutation_reader::forwarding) {
        return fn(std::move(s), std::move(permit), range, slice, pc, std::move(tr), fwd);
    }) {}
    mutation_source(std::function<flat_mutation_reader(schema_ptr, reader_permit, partition_range, const query::partition_slice&, io_priority)> fn)
        : mutation_source([fn = std::move(fn)] (schema_ptr s,
                    reader_permit permit,
                    partition_range range,
                    const query::partition_slice& slice,
                    io_priority pc,
                    tracing::trace_state_ptr,
                    streamed_mutation::forwarding fwd,
                    mutation_reader::forwarding) {
        assert(!fwd);
        return fn(std::move(s), std::move(permit), range, slice, pc);
    }) {}
    mutation_source(std::function<flat_mutation_reader(schema_ptr, reader_permit, partition_range, const query::partition_slice&)> fn)
        : mutation_source([fn = std::move(fn)] (schema_ptr s,
                    reader_permit permit,
                    partition_range range,
                    const query::partition_slice& slice,
                    io_priority,
                    tracing::trace_state_ptr,
                    streamed_mutation::forwarding fwd,
                    mutation_reader::forwarding) {
        assert(!fwd);
        return fn(std::move(s), std::move(permit), range, slice);
    }) {}
    mutation_source(std::function<flat_mutation_reader(schema_ptr, reader_permit, partition_range range)> fn)
        : mutation_source([fn = std::move(fn)] (schema_ptr s,
                    reader_permit permit,
                    partition_range range,
                    const query::partition_slice&,
                    io_priority,
                    tracing::trace_state_ptr,
                    streamed_mutation::forwarding fwd,
                    mutation_reader::forwarding) {
        assert(!fwd);
        return fn(std::move(s), std::move(permit), range);
    }) {}

    mutation_source(std::function<flat_mutation_reader_v2(schema_ptr, reader_permit, partition_range, const query::partition_slice&, io_priority,
                tracing::trace_state_ptr, streamed_mutation::forwarding)> fn)
        : mutation_source([fn = std::move(fn)] (schema_ptr s,
                    reader_permit permit,
                    partition_range range,
                    const query::partition_slice& slice,
                    io_priority pc,
                    tracing::trace_state_ptr tr,
                    streamed_mutation::forwarding fwd,
                    mutation_reader::forwarding) {
        return fn(std::move(s), std::move(permit), range, slice, pc, std::move(tr), fwd);
    }) {}
    mutation_source(std::function<flat_mutation_reader_v2(schema_ptr, reader_permit, partition_range, const query::partition_slice&, io_priority)> fn)
        : mutation_source([fn = std::move(fn)] (schema_ptr s,
                    reader_permit permit,
                    partition_range range,
                    const query::partition_slice& slice,
                    io_priority pc,
                    tracing::trace_state_ptr,
                    streamed_mutation::forwarding fwd,
                    mutation_reader::forwarding) {
        assert(!fwd);
        return fn(std::move(s), std::move(permit), range, slice, pc);
    }) {}
    mutation_source(std::function<flat_mutation_reader_v2(schema_ptr, reader_permit, partition_range, const query::partition_slice&)> fn)
        : mutation_source([fn = std::move(fn)] (schema_ptr s,
                    reader_permit permit,
                    partition_range range,
                    const query::partition_slice& slice,
                    io_priority,
                    tracing::trace_state_ptr,
                    streamed_mutation::forwarding fwd,
                    mutation_reader::forwarding) {
        assert(!fwd);
        return fn(std::move(s), std::move(permit), range, slice);
    }) {}
    mutation_source(std::function<flat_mutation_reader_v2(schema_ptr, reader_permit, partition_range range)> fn)
        : mutation_source([fn = std::move(fn)] (schema_ptr s,
                    reader_permit permit,
                    partition_range range,
                    const query::partition_slice&,
                    io_priority,
                    tracing::trace_state_ptr,
                    streamed_mutation::forwarding fwd,
                    mutation_reader::forwarding) {
        assert(!fwd);
        return fn(std::move(s), std::move(permit), range);
    }) {}

    mutation_source(const mutation_source& other) = default;
    mutation_source& operator=(const mutation_source& other) = default;
    mutation_source(mutation_source&&) = default;
    mutation_source& operator=(mutation_source&&) = default;

    // Creates a new reader.
    //
    // All parameters captured by reference must remain live as long as returned
    // mutation_reader or streamed_mutation obtained through it are alive.
    flat_mutation_reader
    make_reader(
        schema_ptr s,
        reader_permit permit,
        partition_range range,
        const query::partition_slice& slice,
        io_priority pc = default_priority_class(),
        tracing::trace_state_ptr trace_state = nullptr,
        streamed_mutation::forwarding fwd = streamed_mutation::forwarding::no,
        mutation_reader::forwarding fwd_mr = mutation_reader::forwarding::yes) const
    {
        if (_fn_v2) {
            return downgrade_to_v1(
                    (*_fn_v2)(std::move(s), std::move(permit), range, slice, pc, std::move(trace_state), fwd, fwd_mr));
        }
        return (*_fn)(std::move(s), std::move(permit), range, slice, pc, std::move(trace_state), fwd, fwd_mr);
    }

    flat_mutation_reader
    make_reader(
        schema_ptr s,
        reader_permit permit,
        partition_range range = query::full_partition_range) const
    {
        auto& full_slice = s->full_slice();
        return this->make_reader(std::move(s), std::move(permit), range, full_slice);
    }

    // Creates a new reader.
    //
    // All parameters captured by reference must remain live as long as returned
    // mutation_reader or streamed_mutation obtained through it are alive.
    flat_mutation_reader_v2
    make_reader_v2(
            schema_ptr s,
            reader_permit permit,
            partition_range range,
            const query::partition_slice& slice,
            io_priority pc = default_priority_class(),
            tracing::trace_state_ptr trace_state = nullptr,
            streamed_mutation::forwarding fwd = streamed_mutation::forwarding::no,
            mutation_reader::forwarding fwd_mr = mutation_reader::forwarding::yes) const
    {
        if (_fn_v2) {
            return (*_fn_v2)(std::move(s), std::move(permit), range, slice, pc, std::move(trace_state), fwd, fwd_mr);
        }
        return upgrade_to_v2(
                (*_fn)(std::move(s), std::move(permit), range, slice, pc, std::move(trace_state), fwd, fwd_mr));
    }

    flat_mutation_reader_v2
    make_reader_v2(
            schema_ptr s,
            reader_permit permit,
            partition_range range = query::full_partition_range) const
    {
        auto& full_slice = s->full_slice();
        return make_reader_v2(std::move(s), std::move(permit), range, full_slice);
    }

    partition_presence_checker make_partition_presence_checker() {
        return (*_presence_checker_factory)();
    }

    enum class version { v1, v2 };
    version native_version() const { return _fn ? version::v1 : version::v2; }
};

// Returns a mutation_source which is the sum of given mutation_sources.
//
// Adding two mutation sources gives a mutation source which contains
// the sum of writes contained in the addends.
mutation_source make_combined_mutation_source(std::vector<mutation_source>);

// Represent mutation_source which can be snapshotted.
class snapshot_source {
private:
    std::function<mutation_source()> _func;
public:
    snapshot_source(std::function<mutation_source()> func)
        : _func(std::move(func))
    { }

    // Creates a new snapshot.
    // The returned mutation_source represents all earlier writes and only those.
    // Note though that the mutations in the snapshot may get compacted over time.
    mutation_source operator()() {
        return _func();
    }
};

mutation_source make_empty_mutation_source();
snapshot_source make_empty_snapshot_source();

using mutation_source_opt = optimized_optional<mutation_source>;
<commit_msg>mutation_source: add ::make_fragment_v1_stream()<commit_after>/*
 * Copyright (C) 2022-present ScyllaDB
 */

/*
 * SPDX-License-Identifier: AGPL-3.0-or-later
 */

#pragma once

#include <seastar/core/io_priority_class.hh>
#include "dht/i_partitioner.hh"
#include "query-request.hh"
#include "tracing/trace_state.hh"
#include "readers/flat_mutation_reader.hh"
#include "readers/flat_mutation_reader_v2.hh"
#include "readers/mutation_fragment_v1_stream.hh"

/// A partition_presence_checker quickly returns whether a key is known not to exist
/// in a data source (it may return false positives, but not false negatives).
enum class partition_presence_checker_result {
    definitely_doesnt_exist,
    maybe_exists
};
using partition_presence_checker = std::function<partition_presence_checker_result (const dht::decorated_key& key)>;

inline
partition_presence_checker make_default_partition_presence_checker() {
    return [] (const dht::decorated_key&) { return partition_presence_checker_result::maybe_exists; };
}

// mutation_source represents source of data in mutation form. The data source
// can be queried multiple times and in parallel. For each query it returns
// independent mutation_reader.
//
// The reader returns mutations having all the same schema, the one passed
// when invoking the source.
//
// When reading in reverse, a reverse schema has to be passed (compared to the
// table's schema), and a half-reverse (legacy) slice.
// See docs/design-notes/reverse-reads.md for more details.
// Partition-range forwarding is not yet supported in reverse mode.
class mutation_source {
    using partition_range = const dht::partition_range&;
    using io_priority = const io_priority_class&;
    using flat_reader_factory_type = std::function<flat_mutation_reader(schema_ptr,
                                                                        reader_permit,
                                                                        partition_range,
                                                                        const query::partition_slice&,
                                                                        io_priority,
                                                                        tracing::trace_state_ptr,
                                                                        streamed_mutation::forwarding,
                                                                        mutation_reader::forwarding)>;
    using flat_reader_v2_factory_type = std::function<flat_mutation_reader_v2(schema_ptr,
                                                                        reader_permit,
                                                                        partition_range,
                                                                        const query::partition_slice&,
                                                                        io_priority,
                                                                        tracing::trace_state_ptr,
                                                                        streamed_mutation::forwarding,
                                                                        mutation_reader::forwarding)>;
    // We could have our own version of std::function<> that is nothrow
    // move constructible and save some indirection and allocation.
    // Probably not worth the effort though.
    // Either _fn or _fn_v2 is engaged.
    lw_shared_ptr<flat_reader_factory_type> _fn;
    lw_shared_ptr<flat_reader_v2_factory_type> _fn_v2;
    lw_shared_ptr<std::function<partition_presence_checker()>> _presence_checker_factory;
private:
    static flat_mutation_reader_v2 upgrade_to_v2(flat_mutation_reader rd);
    mutation_source() = default;
    explicit operator bool() const { return bool(_fn) || bool(_fn_v2); }
    friend class optimized_optional<mutation_source>;
public:
    mutation_source(flat_reader_factory_type fn, std::function<partition_presence_checker()> pcf = [] { return make_default_partition_presence_checker(); })
        : _fn(make_lw_shared<flat_reader_factory_type>(std::move(fn)))
        , _presence_checker_factory(make_lw_shared<std::function<partition_presence_checker()>>(std::move(pcf)))
    { }

    mutation_source(flat_reader_v2_factory_type fn, std::function<partition_presence_checker()> pcf = [] { return make_default_partition_presence_checker(); })
        : _fn_v2(make_lw_shared<flat_reader_v2_factory_type>(std::move(fn)))
        , _presence_checker_factory(make_lw_shared<std::function<partition_presence_checker()>>(std::move(pcf)))
    { }

    // For sources which don't care about the mutation_reader::forwarding flag (always fast forwardable)
    mutation_source(std::function<flat_mutation_reader(schema_ptr, reader_permit, partition_range, const query::partition_slice&, io_priority,
                tracing::trace_state_ptr, streamed_mutation::forwarding)> fn)
        : mutation_source([fn = std::move(fn)] (schema_ptr s,
                    reader_permit permit,
                    partition_range range,
                    const query::partition_slice& slice,
                    io_priority pc,
                    tracing::trace_state_ptr tr,
                    streamed_mutation::forwarding fwd,
                    mutation_reader::forwarding) {
        return fn(std::move(s), std::move(permit), range, slice, pc, std::move(tr), fwd);
    }) {}
    mutation_source(std::function<flat_mutation_reader(schema_ptr, reader_permit, partition_range, const query::partition_slice&, io_priority)> fn)
        : mutation_source([fn = std::move(fn)] (schema_ptr s,
                    reader_permit permit,
                    partition_range range,
                    const query::partition_slice& slice,
                    io_priority pc,
                    tracing::trace_state_ptr,
                    streamed_mutation::forwarding fwd,
                    mutation_reader::forwarding) {
        assert(!fwd);
        return fn(std::move(s), std::move(permit), range, slice, pc);
    }) {}
    mutation_source(std::function<flat_mutation_reader(schema_ptr, reader_permit, partition_range, const query::partition_slice&)> fn)
        : mutation_source([fn = std::move(fn)] (schema_ptr s,
                    reader_permit permit,
                    partition_range range,
                    const query::partition_slice& slice,
                    io_priority,
                    tracing::trace_state_ptr,
                    streamed_mutation::forwarding fwd,
                    mutation_reader::forwarding) {
        assert(!fwd);
        return fn(std::move(s), std::move(permit), range, slice);
    }) {}
    mutation_source(std::function<flat_mutation_reader(schema_ptr, reader_permit, partition_range range)> fn)
        : mutation_source([fn = std::move(fn)] (schema_ptr s,
                    reader_permit permit,
                    partition_range range,
                    const query::partition_slice&,
                    io_priority,
                    tracing::trace_state_ptr,
                    streamed_mutation::forwarding fwd,
                    mutation_reader::forwarding) {
        assert(!fwd);
        return fn(std::move(s), std::move(permit), range);
    }) {}

    mutation_source(std::function<flat_mutation_reader_v2(schema_ptr, reader_permit, partition_range, const query::partition_slice&, io_priority,
                tracing::trace_state_ptr, streamed_mutation::forwarding)> fn)
        : mutation_source([fn = std::move(fn)] (schema_ptr s,
                    reader_permit permit,
                    partition_range range,
                    const query::partition_slice& slice,
                    io_priority pc,
                    tracing::trace_state_ptr tr,
                    streamed_mutation::forwarding fwd,
                    mutation_reader::forwarding) {
        return fn(std::move(s), std::move(permit), range, slice, pc, std::move(tr), fwd);
    }) {}
    mutation_source(std::function<flat_mutation_reader_v2(schema_ptr, reader_permit, partition_range, const query::partition_slice&, io_priority)> fn)
        : mutation_source([fn = std::move(fn)] (schema_ptr s,
                    reader_permit permit,
                    partition_range range,
                    const query::partition_slice& slice,
                    io_priority pc,
                    tracing::trace_state_ptr,
                    streamed_mutation::forwarding fwd,
                    mutation_reader::forwarding) {
        assert(!fwd);
        return fn(std::move(s), std::move(permit), range, slice, pc);
    }) {}
    mutation_source(std::function<flat_mutation_reader_v2(schema_ptr, reader_permit, partition_range, const query::partition_slice&)> fn)
        : mutation_source([fn = std::move(fn)] (schema_ptr s,
                    reader_permit permit,
                    partition_range range,
                    const query::partition_slice& slice,
                    io_priority,
                    tracing::trace_state_ptr,
                    streamed_mutation::forwarding fwd,
                    mutation_reader::forwarding) {
        assert(!fwd);
        return fn(std::move(s), std::move(permit), range, slice);
    }) {}
    mutation_source(std::function<flat_mutation_reader_v2(schema_ptr, reader_permit, partition_range range)> fn)
        : mutation_source([fn = std::move(fn)] (schema_ptr s,
                    reader_permit permit,
                    partition_range range,
                    const query::partition_slice&,
                    io_priority,
                    tracing::trace_state_ptr,
                    streamed_mutation::forwarding fwd,
                    mutation_reader::forwarding) {
        assert(!fwd);
        return fn(std::move(s), std::move(permit), range);
    }) {}

    mutation_source(const mutation_source& other) = default;
    mutation_source& operator=(const mutation_source& other) = default;
    mutation_source(mutation_source&&) = default;
    mutation_source& operator=(mutation_source&&) = default;

    mutation_fragment_v1_stream
    make_fragment_v1_stream(
        schema_ptr s,
        reader_permit permit,
        partition_range range,
        const query::partition_slice& slice,
        io_priority pc = default_priority_class(),
        tracing::trace_state_ptr trace_state = nullptr,
        streamed_mutation::forwarding fwd = streamed_mutation::forwarding::no,
        mutation_reader::forwarding fwd_mr = mutation_reader::forwarding::yes) const
    {
        if (_fn_v2) {
            return mutation_fragment_v1_stream(
                    (*_fn_v2)(std::move(s), std::move(permit), range, slice, pc, std::move(trace_state), fwd, fwd_mr));
        }
        return mutation_fragment_v1_stream(upgrade_to_v2((*_fn)(std::move(s), std::move(permit), range, slice, pc, std::move(trace_state), fwd, fwd_mr)));
    }

    mutation_fragment_v1_stream
    make_fragment_v1_stream(
        schema_ptr s,
        reader_permit permit,
        partition_range range = query::full_partition_range) const
    {
        auto& full_slice = s->full_slice();
        return this->make_fragment_v1_stream(std::move(s), std::move(permit), range, full_slice);
    }

    // Creates a new reader.
    //
    // All parameters captured by reference must remain live as long as returned
    // mutation_reader or streamed_mutation obtained through it are alive.
    flat_mutation_reader
    make_reader(
        schema_ptr s,
        reader_permit permit,
        partition_range range,
        const query::partition_slice& slice,
        io_priority pc = default_priority_class(),
        tracing::trace_state_ptr trace_state = nullptr,
        streamed_mutation::forwarding fwd = streamed_mutation::forwarding::no,
        mutation_reader::forwarding fwd_mr = mutation_reader::forwarding::yes) const
    {
        if (_fn_v2) {
            return downgrade_to_v1(
                    (*_fn_v2)(std::move(s), std::move(permit), range, slice, pc, std::move(trace_state), fwd, fwd_mr));
        }
        return (*_fn)(std::move(s), std::move(permit), range, slice, pc, std::move(trace_state), fwd, fwd_mr);
    }

    flat_mutation_reader
    make_reader(
        schema_ptr s,
        reader_permit permit,
        partition_range range = query::full_partition_range) const
    {
        auto& full_slice = s->full_slice();
        return this->make_reader(std::move(s), std::move(permit), range, full_slice);
    }

    // Creates a new reader.
    //
    // All parameters captured by reference must remain live as long as returned
    // mutation_reader or streamed_mutation obtained through it are alive.
    flat_mutation_reader_v2
    make_reader_v2(
            schema_ptr s,
            reader_permit permit,
            partition_range range,
            const query::partition_slice& slice,
            io_priority pc = default_priority_class(),
            tracing::trace_state_ptr trace_state = nullptr,
            streamed_mutation::forwarding fwd = streamed_mutation::forwarding::no,
            mutation_reader::forwarding fwd_mr = mutation_reader::forwarding::yes) const
    {
        if (_fn_v2) {
            return (*_fn_v2)(std::move(s), std::move(permit), range, slice, pc, std::move(trace_state), fwd, fwd_mr);
        }
        return upgrade_to_v2(
                (*_fn)(std::move(s), std::move(permit), range, slice, pc, std::move(trace_state), fwd, fwd_mr));
    }

    flat_mutation_reader_v2
    make_reader_v2(
            schema_ptr s,
            reader_permit permit,
            partition_range range = query::full_partition_range) const
    {
        auto& full_slice = s->full_slice();
        return make_reader_v2(std::move(s), std::move(permit), range, full_slice);
    }

    partition_presence_checker make_partition_presence_checker() {
        return (*_presence_checker_factory)();
    }

    enum class version { v1, v2 };
    version native_version() const { return _fn ? version::v1 : version::v2; }
};

// Returns a mutation_source which is the sum of given mutation_sources.
//
// Adding two mutation sources gives a mutation source which contains
// the sum of writes contained in the addends.
mutation_source make_combined_mutation_source(std::vector<mutation_source>);

// Represent mutation_source which can be snapshotted.
class snapshot_source {
private:
    std::function<mutation_source()> _func;
public:
    snapshot_source(std::function<mutation_source()> func)
        : _func(std::move(func))
    { }

    // Creates a new snapshot.
    // The returned mutation_source represents all earlier writes and only those.
    // Note though that the mutations in the snapshot may get compacted over time.
    mutation_source operator()() {
        return _func();
    }
};

mutation_source make_empty_mutation_source();
snapshot_source make_empty_snapshot_source();

using mutation_source_opt = optimized_optional<mutation_source>;
<|endoftext|>