<commit_before>/** @copyright
 * Copyright (c) 2020 Stuart W Baker
 * 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.
 *
 * 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 HOLDER 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.
 *
 * @file SN74HC595GPO.hxx
 * This file implements the GPO driver for the 74HC595 shift register. The SN
 * prefix is for the Texas Instruments variant, however compatible devices
 * from other suppliers may have a different prefix or no prefix.
 *
 * @author Stuart W. Baker
 * @date 23 February 2020
 */

#ifndef _FREERTOS_DRIVERS_COMMON_SN74HC595GPO_HXX_
#define _FREERTOS_DRIVERS_COMMON_SN74HC595GPO_HXX_

#include <atomic>
#include <cstddef>
#include <cstdint>
#include <fcntl.h>
#include <unistd.h>

#include "SPI.hxx"

#include "os/Gpio.hxx"
#include "os/OS.hxx"

template <uint8_t N = 1> class SN74HC595GPO;

/// Driver for the 74HC595 shift register. Note: This driver makes use of
/// std::atomic and requires an implementation of std::atomic on any platform
/// that makes use of it. For example, at the time of creating this device
/// driver, ARMv7-M (Cortex-M3/M4/M4F) does have support for std::atomic,
/// while ARMv6-M (Cortex-M0) does not.
/// @tparam N number of chips on the bus, starting at 1
template <uint8_t N = 1> class SN74HC595 : public OSThread
{
public:
    /// Constructor.
    /// @param request_refresh_operation This is an application specific
    ///        callback for triggering a sequence of events that will result
    ///        in @ref refresh() being called. The exact implementation is
    ///        application specific, and mostly is determined by whether or not
    ///        these outputs must be toggled from an interrupt.
    SN74HC595(void (*request_refresh_operation)(void))
        : requestRefreshOperation_(request_refresh_operation)
        , spiFd_(-1)
        , sem_()
        , ioPending_(false)
    {
        HASSERT(N > 0);
        for (unsigned i = 0; i < N; ++i)
        {
            gpoData_[i] = 0;
        }
    }

    /// Initialize the SN74HC595 settings. Typically called in hw_postinit(),
    /// not hw_preinit() or hw_init().
    /// @param spi_name spi interface that the SN74HC595 is on
    /// @param priority helper thread priority
    void init(const char *spi_name, int priority = get_priority_max())
    {
        spiFd_ = ::open(spi_name, O_WRONLY);
        HASSERT(spiFd_ >= 0);

        // configure SPI bus settings
        uint8_t spi_mode = SPI_MODE_0;
        uint8_t spi_bpw = 8;
        uint32_t spi_max_speed_hz = SPI_MAX_SPEED_HZ;
        ::ioctl(spiFd_, SPI_IOC_WR_MODE, &spi_mode);
        ::ioctl(spiFd_, SPI_IOC_WR_BITS_PER_WORD, &spi_bpw);
        ::ioctl(spiFd_, SPI_IOC_WR_MAX_SPEED_HZ, &spi_max_speed_hz);

        requestRefreshOperation_();

        // start the thread at the highest priority in the system
        start("SN74HC595", priority, 384 + N);
    }

    /// Triggers the helper thread to wakeup and refresh the outputs.
    /// @param from_isr true if called from an ISR.
    void refresh(bool from_isr = false)
    {
        if (!ioPending_)
        {
            ioPending_ = true;
            if (from_isr)
            {
                int woken;
                sem_.post_from_isr(&woken);
            }
            else
            {
                sem_.post();
            }
        }
    }

private:
    /// maximum SPI clock speed in Hz
    static constexpr uint32_t SPI_MAX_SPEED_HZ = 1000000;

    /// User entry point for the created thread.
    /// @return exit status
    void *entry() override
    {
        for ( ; /* forever */ ; )
        {
            sem_.wait();
            if (ioPending_)
            {
                ioPending_ = false;
                uint8_t data[N];
                for (unsigned i = 0; i < N; ++i)
                {
                    data[i] = gpoData_[i];
                }
                ::write(spiFd_, data, N);
            }
        }
    }

    /// Request that the GPIO cache be refreshed.
    void (*requestRefreshOperation_)(void);

    int spiFd_; ///< SPI bus that accesses the SN74HC595
    OSSem sem_; ///< semaphore for posting events
    uint8_t ioPending_ : 1; ///< true if an update is pending

    /// local copy of the expansion output data
    std::atomic<uint8_t> gpoData_[N];

    /// Allow access to SN74HC595 from SN74HC595GPO
    friend class SN74HC595GPO<N>;

    DISALLOW_COPY_AND_ASSIGN(SN74HC595);
};

/// General Purpose Output (GPO) instance on the 74HC595.
/// @tparam N number of chips on the bus, starting at 1
template <uint8_t N> class SN74HC595GPO : public Gpio
{
public:
    /// Constructor.
    /// @param instance parrent 74HC595 instance that "owns" the interface.
    /// @param chip_index index on the bus for the chip, starting at 0.
    /// @param bit bit index (0 through 7) of the output.
    constexpr SN74HC595GPO(SN74HC595<N> *instance, uint8_t chip_index, uint8_t bit)
        : Gpio()
        , instance_(instance)
        , chipIndex_(chip_index)
        , bit_(bit)
    {
        HASSERT(bit < 8);
        HASSERT(chip_index < sizeof(instance->gpoData_));
        HASSERT(N == sizeof(instance->gpoData_));
    }

    /// Writes a GPO pin (set or clear to a specific state).
    /// @param new_state the desired output state.  See @ref Value.
    void write(Value new_state) const override
    {
        new_state ? set() : clr();
    }

    /// Retrieves the current @ref Value of a GPO output sate (requested).
    /// @return @ref SET if currently high, @ref CLR if currently low
    Value read() const override
    {
        return instance_->gpoData_[chipIndex_] & (0x1 << bit_) ?
                   Gpio::SET : Gpio::CLR;
    }

    /// Sets the GPO pin to high.
    void set() const override
    {
        if (!(instance_->gpoData_[chipIndex_] & (0x1 << bit_)))
        {
            instance_->gpoData_[chipIndex_] |= 0x1 << bit_;
            instance_->requestRefreshOperation_();
        }
    }

    /// Clears the GPO pin to low.
    void clr() const override
    {
        if ((instance_->gpoData_[chipIndex_] & (0x1 << bit_)))
        {
            instance_->gpoData_[chipIndex_] &= ~(0x1 << bit_);
            instance_->requestRefreshOperation_();
        }
    }

    /// Sets the GPO direction (does nothing).
    /// @param dir @ref DINPUT or @ref DOUTPUT
    void set_direction(Gpio::Direction dir) const override
    {
        HASSERT(dir == Gpio::Direction::DOUTPUT);
    }

    /// Gets the GPO direction.
    /// @return always returns @ref DOUTPUT
    Direction direction() const override
    {
        return Gpio::Direction::DOUTPUT;
    }

private:
    /// reference to chip instance
    SN74HC595<N> * const instance_;

    /// index on the bus for the chip
    const uint8_t chipIndex_;

    /// bit number representative of the bit
    const uint8_t bit_;

    DISALLOW_COPY_AND_ASSIGN(SN74HC595GPO);
};

#endif // _FREERTOS_DRIVERS_COMMON_SN74HC595GPO_HXX_
<commit_msg>Increase the MAX supported SPI clock speed. (#366)<commit_after>/** @copyright
 * Copyright (c) 2020 Stuart W Baker
 * 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.
 *
 * 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 HOLDER 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.
 *
 * @file SN74HC595GPO.hxx
 * This file implements the GPO driver for the 74HC595 shift register. The SN
 * prefix is for the Texas Instruments variant, however compatible devices
 * from other suppliers may have a different prefix or no prefix.
 *
 * @author Stuart W. Baker
 * @date 23 February 2020
 */

#ifndef _FREERTOS_DRIVERS_COMMON_SN74HC595GPO_HXX_
#define _FREERTOS_DRIVERS_COMMON_SN74HC595GPO_HXX_

#include <atomic>
#include <cstddef>
#include <cstdint>
#include <fcntl.h>
#include <unistd.h>

#include "SPI.hxx"

#include "os/Gpio.hxx"
#include "os/OS.hxx"

template <uint8_t N = 1> class SN74HC595GPO;

/// Driver for the 74HC595 shift register. Note: This driver makes use of
/// std::atomic and requires an implementation of std::atomic on any platform
/// that makes use of it. For example, at the time of creating this device
/// driver, ARMv7-M (Cortex-M3/M4/M4F) does have support for std::atomic,
/// while ARMv6-M (Cortex-M0) does not.
/// @tparam N number of chips on the bus, starting at 1
template <uint8_t N = 1> class SN74HC595 : public OSThread
{
public:
    /// Constructor.
    /// @param request_refresh_operation This is an application specific
    ///        callback for triggering a sequence of events that will result
    ///        in @ref refresh() being called. The exact implementation is
    ///        application specific, and mostly is determined by whether or not
    ///        these outputs must be toggled from an interrupt.
    SN74HC595(void (*request_refresh_operation)(void))
        : requestRefreshOperation_(request_refresh_operation)
        , spiFd_(-1)
        , sem_()
        , ioPending_(false)
    {
        HASSERT(N > 0);
        for (unsigned i = 0; i < N; ++i)
        {
            gpoData_[i] = 0;
        }
    }

    /// Initialize the SN74HC595 settings. Typically called in hw_postinit(),
    /// not hw_preinit() or hw_init().
    /// @param spi_name spi interface that the SN74HC595 is on
    /// @param priority helper thread priority
    void init(const char *spi_name, int priority = get_priority_max())
    {
        spiFd_ = ::open(spi_name, O_WRONLY);
        HASSERT(spiFd_ >= 0);

        // configure SPI bus settings
        uint8_t spi_mode = SPI_MODE_0;
        uint8_t spi_bpw = 8;
        uint32_t spi_max_speed_hz = SPI_MAX_SPEED_HZ;
        ::ioctl(spiFd_, SPI_IOC_WR_MODE, &spi_mode);
        ::ioctl(spiFd_, SPI_IOC_WR_BITS_PER_WORD, &spi_bpw);
        ::ioctl(spiFd_, SPI_IOC_WR_MAX_SPEED_HZ, &spi_max_speed_hz);

        requestRefreshOperation_();

        // start the thread at the highest priority in the system
        start("SN74HC595", priority, 384 + N);
    }

    /// Triggers the helper thread to wakeup and refresh the outputs.
    /// @param from_isr true if called from an ISR.
    void refresh(bool from_isr = false)
    {
        if (!ioPending_)
        {
            ioPending_ = true;
            if (from_isr)
            {
                int woken;
                sem_.post_from_isr(&woken);
            }
            else
            {
                sem_.post();
            }
        }
    }

private:
    /// maximum SPI clock speed in Hz
    static constexpr uint32_t SPI_MAX_SPEED_HZ = 4000000;

    /// User entry point for the created thread.
    /// @return exit status
    void *entry() override
    {
        for ( ; /* forever */ ; )
        {
            sem_.wait();
            if (ioPending_)
            {
                ioPending_ = false;
                uint8_t data[N];
                for (unsigned i = 0; i < N; ++i)
                {
                    data[i] = gpoData_[i];
                }
                ::write(spiFd_, data, N);
            }
        }
    }

    /// Request that the GPIO cache be refreshed.
    void (*requestRefreshOperation_)(void);

    int spiFd_; ///< SPI bus that accesses the SN74HC595
    OSSem sem_; ///< semaphore for posting events
    uint8_t ioPending_ : 1; ///< true if an update is pending

    /// local copy of the expansion output data
    std::atomic<uint8_t> gpoData_[N];

    /// Allow access to SN74HC595 from SN74HC595GPO
    friend class SN74HC595GPO<N>;

    DISALLOW_COPY_AND_ASSIGN(SN74HC595);
};

/// General Purpose Output (GPO) instance on the 74HC595.
/// @tparam N number of chips on the bus, starting at 1
template <uint8_t N> class SN74HC595GPO : public Gpio
{
public:
    /// Constructor.
    /// @param instance parrent 74HC595 instance that "owns" the interface.
    /// @param chip_index index on the bus for the chip, starting at 0.
    /// @param bit bit index (0 through 7) of the output.
    constexpr SN74HC595GPO(SN74HC595<N> *instance, uint8_t chip_index, uint8_t bit)
        : Gpio()
        , instance_(instance)
        , chipIndex_(chip_index)
        , bit_(bit)
    {
        HASSERT(bit < 8);
        HASSERT(chip_index < sizeof(instance->gpoData_));
        HASSERT(N == sizeof(instance->gpoData_));
    }

    /// Writes a GPO pin (set or clear to a specific state).
    /// @param new_state the desired output state.  See @ref Value.
    void write(Value new_state) const override
    {
        new_state ? set() : clr();
    }

    /// Retrieves the current @ref Value of a GPO output sate (requested).
    /// @return @ref SET if currently high, @ref CLR if currently low
    Value read() const override
    {
        return instance_->gpoData_[chipIndex_] & (0x1 << bit_) ?
                   Gpio::SET : Gpio::CLR;
    }

    /// Sets the GPO pin to high.
    void set() const override
    {
        if (!(instance_->gpoData_[chipIndex_] & (0x1 << bit_)))
        {
            instance_->gpoData_[chipIndex_] |= 0x1 << bit_;
            instance_->requestRefreshOperation_();
        }
    }

    /// Clears the GPO pin to low.
    void clr() const override
    {
        if ((instance_->gpoData_[chipIndex_] & (0x1 << bit_)))
        {
            instance_->gpoData_[chipIndex_] &= ~(0x1 << bit_);
            instance_->requestRefreshOperation_();
        }
    }

    /// Sets the GPO direction (does nothing).
    /// @param dir @ref DINPUT or @ref DOUTPUT
    void set_direction(Gpio::Direction dir) const override
    {
        HASSERT(dir == Gpio::Direction::DOUTPUT);
    }

    /// Gets the GPO direction.
    /// @return always returns @ref DOUTPUT
    Direction direction() const override
    {
        return Gpio::Direction::DOUTPUT;
    }

private:
    /// reference to chip instance
    SN74HC595<N> * const instance_;

    /// index on the bus for the chip
    const uint8_t chipIndex_;

    /// bit number representative of the bit
    const uint8_t bit_;

    DISALLOW_COPY_AND_ASSIGN(SN74HC595GPO);
};

#endif // _FREERTOS_DRIVERS_COMMON_SN74HC595GPO_HXX_
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "src/ftrace_reader/proto_translation_table.h"

#include <regex.h>

#include <algorithm>

#include "event_info.h"
#include "ftrace_procfs.h"
#include "perfetto/ftrace_reader/format_parser.h"

#include "perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"

namespace perfetto {

namespace {

const std::vector<Event> BuildEventsVector(const std::vector<Event>& events) {
  size_t largest_id = 0;
  for (const Event& event : events) {
    if (event.ftrace_event_id > largest_id)
      largest_id = event.ftrace_event_id;
  }
  std::vector<Event> events_by_id;
  events_by_id.resize(largest_id + 1);
  for (const Event& event : events) {
    events_by_id[event.ftrace_event_id] = event;
  }
  events_by_id.shrink_to_fit();
  return events_by_id;
}

// Merge the information from |ftrace_field| into |field| (mutating it).
// We should set the following fields: offset, size, ftrace field type and
// translation strategy.
bool MergeFieldInfo(const FtraceEvent::Field& ftrace_field,
                    Field* field,
                    const char* event_name_for_debug) {
  PERFETTO_DCHECK(field->ftrace_name);
  PERFETTO_DCHECK(field->proto_field_id);
  PERFETTO_DCHECK(field->proto_field_type);
  PERFETTO_DCHECK(!field->ftrace_offset);
  PERFETTO_DCHECK(!field->ftrace_size);
  PERFETTO_DCHECK(!field->ftrace_type);

  if (!InferFtraceType(ftrace_field.type_and_name, ftrace_field.size,
                       ftrace_field.is_signed, &field->ftrace_type)) {
    PERFETTO_DLOG(
        "Failed to infer ftrace field type for \"%s.%s\" (type:\"%s\" size:%d "
        "signed:%d)",
        event_name_for_debug, field->ftrace_name,
        ftrace_field.type_and_name.c_str(), ftrace_field.size,
        ftrace_field.is_signed);
    PERFETTO_DCHECK(false);
    return false;
  }

  field->ftrace_offset = ftrace_field.offset;
  field->ftrace_size = ftrace_field.size;

  if (!SetTranslationStrategy(field->ftrace_type, field->proto_field_type,
                              &field->strategy)) {
    PERFETTO_DLOG(
        "Failed to find translation stratagy for ftrace field \"%s.%s\" (%s -> "
        "%s)",
        event_name_for_debug, field->ftrace_name, ToString(field->ftrace_type),
        ToString(field->proto_field_type));
    // TODO(hjd): Uncomment DCHECK when proto generation is fixed.
    // PERFETTO_DCHECK(false);
    return false;
  }

  return true;
}

// For each field in |fields| find the matching field from |ftrace_fields| (by
// comparing ftrace_name) and copy the information from the FtraceEvent::Field
// into the Field (mutating it). If there is no matching field in
// |ftrace_fields| remove the Field from |fields|. Return the maximum observed
// 'field end' (offset + size).
uint16_t MergeFields(const std::vector<FtraceEvent::Field>& ftrace_fields,
                     std::vector<Field>* fields,
                     const char* event_name_for_debug) {
  uint16_t fields_end = 0;

  // Loop over each Field in |fields| modifiying it with information from the
  // matching |ftrace_fields| field or removing it.
  auto field = fields->begin();
  while (field != fields->end()) {
    bool success = false;
    for (const FtraceEvent::Field& ftrace_field : ftrace_fields) {
      if (GetNameFromTypeAndName(ftrace_field.type_and_name) !=
          field->ftrace_name)
        continue;

      success = MergeFieldInfo(ftrace_field, &*field, event_name_for_debug);

      uint16_t field_end = field->ftrace_offset + field->ftrace_size;
      fields_end = std::max<uint16_t>(fields_end, field_end);

      break;
    }
    if (success) {
      ++field;
    } else {
      field = fields->erase(field);
    }
  }
  return fields_end;
}

bool StartsWith(const std::string& str, const std::string& prefix) {
  return str.compare(0, prefix.length(), prefix) == 0;
}

bool Contains(const std::string& haystack, const std::string& needle) {
  return haystack.find(needle) != std::string::npos;
}

std::string RegexError(int errcode, const regex_t* preg) {
  char buf[64];
  regerror(errcode, preg, buf, sizeof(buf));
  return {buf, sizeof(buf)};
}

bool Match(const char* string, const char* pattern) {
  regex_t re;
  int ret = regcomp(&re, pattern, REG_EXTENDED | REG_NOSUB);
  if (ret != 0) {
    PERFETTO_FATAL("regcomp: %s", RegexError(ret, &re).c_str());
  }
  ret = regexec(&re, string, 0, nullptr, 0);
  regfree(&re);
  return ret != REG_NOMATCH;
}

}  // namespace

// This is similar but different from InferProtoType (see format_parser.cc).
// TODO(hjd): Fold FtraceEvent(::Field) into Event.
bool InferFtraceType(const std::string& type_and_name,
                     size_t size,
                     bool is_signed,
                     FtraceFieldType* out) {
  // Fixed length strings: e.g. "char foo[16]" we don't care about the number
  // since we get the size as it's own field. Somewhat awkwardly these fields
  // are both fixed size and null terminated meaning that we can't just drop
  // them directly into the protobuf (since if the string is shorter than 15
  // characters we want only the bit up to the null terminator).
  if (Match(type_and_name.c_str(), R"(char [a-zA-Z_]+\[[0-9]+\])")) {
    *out = kFtraceFixedCString;
    return true;
  }

  // String pointers: "__data_loc char[] foo" (as in
  // 'cpufreq_interactive_boost').
  if (Contains(type_and_name, "char[] ")) {
    *out = kFtraceStringPtr;
    return true;
  }
  if (Contains(type_and_name, "char * ")) {
    *out = kFtraceStringPtr;
    return true;
  }

  // Variable length strings: "char foo" + size: 0 (as in 'print').
  if (StartsWith(type_and_name, "char ") && size == 0) {
    *out = kFtraceCString;
    return true;
  }

  if (StartsWith(type_and_name, "bool ")) {
    *out = kFtraceBool;
    return true;
  }

  if (StartsWith(type_and_name, "ino_t ") ||
      StartsWith(type_and_name, "i_ino ")) {
    if (size == 4) {
      *out = kFtraceInode32;
      return true;
    } else if (size == 8) {
      *out = kFtraceInode64;
      return true;
    }
  }

  // Pids (as in 'sched_switch').
  if (StartsWith(type_and_name, "pid_t ") && size == 4) {
    *out = kFtracePid32;
    return true;
  }

  // Ints of various sizes:
  if (size == 1 && !is_signed) {
    *out = kFtraceUint8;
    return true;
  } else if (size == 2 && is_signed) {
    *out = kFtraceInt16;
    return true;
  } else if (size == 2 && !is_signed) {
    *out = kFtraceUint16;
    return true;
  } else if (size == 4 && is_signed) {
    *out = kFtraceInt32;
    return true;
  } else if (size == 4 && !is_signed) {
    *out = kFtraceUint32;
    return true;
  } else if (size == 8 && is_signed) {
    *out = kFtraceInt64;
    return true;
  } else if (size == 8 && !is_signed) {
    *out = kFtraceUint64;
    return true;
  }

  PERFETTO_DLOG("Could not infer ftrace type for '%s'", type_and_name.c_str());
  return false;
}

// static
std::unique_ptr<ProtoTranslationTable> ProtoTranslationTable::Create(
    const FtraceProcfs* ftrace_procfs,
    std::vector<Event> events,
    std::vector<Field> common_fields) {
  bool common_fields_processed = false;
  uint16_t common_fields_end = 0;

  for (Event& event : events) {
    PERFETTO_DCHECK(event.name);
    PERFETTO_DCHECK(event.group);
    PERFETTO_DCHECK(event.proto_field_id);
    PERFETTO_DCHECK(!event.ftrace_event_id);

    std::string contents =
        ftrace_procfs->ReadEventFormat(event.group, event.name);
    FtraceEvent ftrace_event;
    if (contents.empty() || !ParseFtraceEvent(contents, &ftrace_event)) {
      continue;
    }

    event.ftrace_event_id = ftrace_event.id;

    if (!common_fields_processed) {
      common_fields_end =
          MergeFields(ftrace_event.common_fields, &common_fields, event.name);
      common_fields_processed = true;
    }

    uint16_t fields_end =
        MergeFields(ftrace_event.fields, &event.fields, event.name);

    event.size = std::max<uint16_t>(fields_end, common_fields_end);
  }

  events.erase(std::remove_if(events.begin(), events.end(),
                              [](const Event& event) {
                                return event.proto_field_id == 0 ||
                                       event.ftrace_event_id == 0;
                              }),
               events.end());

  auto table = std::unique_ptr<ProtoTranslationTable>(
      new ProtoTranslationTable(events, std::move(common_fields)));
  return table;
}

ProtoTranslationTable::ProtoTranslationTable(const std::vector<Event>& events,
                                             std::vector<Field> common_fields)
    : events_(BuildEventsVector(events)),
      largest_id_(events_.size() - 1),
      common_fields_(std::move(common_fields)) {
  for (const Event& event : events) {
    name_to_event_[event.name] = &events_.at(event.ftrace_event_id);
  }
}

ProtoTranslationTable::~ProtoTranslationTable() = default;

}  // namespace perfetto
<commit_msg>ftrace_reader: Comment out DCHECK in proto_translation_table.cc<commit_after>/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "src/ftrace_reader/proto_translation_table.h"

#include <regex.h>

#include <algorithm>

#include "event_info.h"
#include "ftrace_procfs.h"
#include "perfetto/ftrace_reader/format_parser.h"

#include "perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"

namespace perfetto {

namespace {

const std::vector<Event> BuildEventsVector(const std::vector<Event>& events) {
  size_t largest_id = 0;
  for (const Event& event : events) {
    if (event.ftrace_event_id > largest_id)
      largest_id = event.ftrace_event_id;
  }
  std::vector<Event> events_by_id;
  events_by_id.resize(largest_id + 1);
  for (const Event& event : events) {
    events_by_id[event.ftrace_event_id] = event;
  }
  events_by_id.shrink_to_fit();
  return events_by_id;
}

// Merge the information from |ftrace_field| into |field| (mutating it).
// We should set the following fields: offset, size, ftrace field type and
// translation strategy.
bool MergeFieldInfo(const FtraceEvent::Field& ftrace_field,
                    Field* field,
                    const char* event_name_for_debug) {
  PERFETTO_DCHECK(field->ftrace_name);
  PERFETTO_DCHECK(field->proto_field_id);
  PERFETTO_DCHECK(field->proto_field_type);
  PERFETTO_DCHECK(!field->ftrace_offset);
  PERFETTO_DCHECK(!field->ftrace_size);
  PERFETTO_DCHECK(!field->ftrace_type);

  if (!InferFtraceType(ftrace_field.type_and_name, ftrace_field.size,
                       ftrace_field.is_signed, &field->ftrace_type)) {
    PERFETTO_DLOG(
        "Failed to infer ftrace field type for \"%s.%s\" (type:\"%s\" size:%d "
        "signed:%d)",
        event_name_for_debug, field->ftrace_name,
        ftrace_field.type_and_name.c_str(), ftrace_field.size,
        ftrace_field.is_signed);
    // TODO(hjd): Uncomment DCHECK when proto generation is fixed.
    // PERFETTO_DCHECK(false);
    return false;
  }

  field->ftrace_offset = ftrace_field.offset;
  field->ftrace_size = ftrace_field.size;

  if (!SetTranslationStrategy(field->ftrace_type, field->proto_field_type,
                              &field->strategy)) {
    PERFETTO_DLOG(
        "Failed to find translation stratagy for ftrace field \"%s.%s\" (%s -> "
        "%s)",
        event_name_for_debug, field->ftrace_name, ToString(field->ftrace_type),
        ToString(field->proto_field_type));
    // TODO(hjd): Uncomment DCHECK when proto generation is fixed.
    // PERFETTO_DCHECK(false);
    return false;
  }

  return true;
}

// For each field in |fields| find the matching field from |ftrace_fields| (by
// comparing ftrace_name) and copy the information from the FtraceEvent::Field
// into the Field (mutating it). If there is no matching field in
// |ftrace_fields| remove the Field from |fields|. Return the maximum observed
// 'field end' (offset + size).
uint16_t MergeFields(const std::vector<FtraceEvent::Field>& ftrace_fields,
                     std::vector<Field>* fields,
                     const char* event_name_for_debug) {
  uint16_t fields_end = 0;

  // Loop over each Field in |fields| modifiying it with information from the
  // matching |ftrace_fields| field or removing it.
  auto field = fields->begin();
  while (field != fields->end()) {
    bool success = false;
    for (const FtraceEvent::Field& ftrace_field : ftrace_fields) {
      if (GetNameFromTypeAndName(ftrace_field.type_and_name) !=
          field->ftrace_name)
        continue;

      success = MergeFieldInfo(ftrace_field, &*field, event_name_for_debug);

      uint16_t field_end = field->ftrace_offset + field->ftrace_size;
      fields_end = std::max<uint16_t>(fields_end, field_end);

      break;
    }
    if (success) {
      ++field;
    } else {
      field = fields->erase(field);
    }
  }
  return fields_end;
}

bool StartsWith(const std::string& str, const std::string& prefix) {
  return str.compare(0, prefix.length(), prefix) == 0;
}

bool Contains(const std::string& haystack, const std::string& needle) {
  return haystack.find(needle) != std::string::npos;
}

std::string RegexError(int errcode, const regex_t* preg) {
  char buf[64];
  regerror(errcode, preg, buf, sizeof(buf));
  return {buf, sizeof(buf)};
}

bool Match(const char* string, const char* pattern) {
  regex_t re;
  int ret = regcomp(&re, pattern, REG_EXTENDED | REG_NOSUB);
  if (ret != 0) {
    PERFETTO_FATAL("regcomp: %s", RegexError(ret, &re).c_str());
  }
  ret = regexec(&re, string, 0, nullptr, 0);
  regfree(&re);
  return ret != REG_NOMATCH;
}

}  // namespace

// This is similar but different from InferProtoType (see format_parser.cc).
// TODO(hjd): Fold FtraceEvent(::Field) into Event.
bool InferFtraceType(const std::string& type_and_name,
                     size_t size,
                     bool is_signed,
                     FtraceFieldType* out) {
  // Fixed length strings: e.g. "char foo[16]" we don't care about the number
  // since we get the size as it's own field. Somewhat awkwardly these fields
  // are both fixed size and null terminated meaning that we can't just drop
  // them directly into the protobuf (since if the string is shorter than 15
  // characters we want only the bit up to the null terminator).
  if (Match(type_and_name.c_str(), R"(char [a-zA-Z_]+\[[0-9]+\])")) {
    *out = kFtraceFixedCString;
    return true;
  }

  // String pointers: "__data_loc char[] foo" (as in
  // 'cpufreq_interactive_boost').
  if (Contains(type_and_name, "char[] ")) {
    *out = kFtraceStringPtr;
    return true;
  }
  if (Contains(type_and_name, "char * ")) {
    *out = kFtraceStringPtr;
    return true;
  }

  // Variable length strings: "char foo" + size: 0 (as in 'print').
  if (StartsWith(type_and_name, "char ") && size == 0) {
    *out = kFtraceCString;
    return true;
  }

  if (StartsWith(type_and_name, "bool ")) {
    *out = kFtraceBool;
    return true;
  }

  if (StartsWith(type_and_name, "ino_t ") ||
      StartsWith(type_and_name, "i_ino ")) {
    if (size == 4) {
      *out = kFtraceInode32;
      return true;
    } else if (size == 8) {
      *out = kFtraceInode64;
      return true;
    }
  }

  // Pids (as in 'sched_switch').
  if (StartsWith(type_and_name, "pid_t ") && size == 4) {
    *out = kFtracePid32;
    return true;
  }

  // Ints of various sizes:
  if (size == 1 && !is_signed) {
    *out = kFtraceUint8;
    return true;
  } else if (size == 2 && is_signed) {
    *out = kFtraceInt16;
    return true;
  } else if (size == 2 && !is_signed) {
    *out = kFtraceUint16;
    return true;
  } else if (size == 4 && is_signed) {
    *out = kFtraceInt32;
    return true;
  } else if (size == 4 && !is_signed) {
    *out = kFtraceUint32;
    return true;
  } else if (size == 8 && is_signed) {
    *out = kFtraceInt64;
    return true;
  } else if (size == 8 && !is_signed) {
    *out = kFtraceUint64;
    return true;
  }

  PERFETTO_DLOG("Could not infer ftrace type for '%s'", type_and_name.c_str());
  return false;
}

// static
std::unique_ptr<ProtoTranslationTable> ProtoTranslationTable::Create(
    const FtraceProcfs* ftrace_procfs,
    std::vector<Event> events,
    std::vector<Field> common_fields) {
  bool common_fields_processed = false;
  uint16_t common_fields_end = 0;

  for (Event& event : events) {
    PERFETTO_DCHECK(event.name);
    PERFETTO_DCHECK(event.group);
    PERFETTO_DCHECK(event.proto_field_id);
    PERFETTO_DCHECK(!event.ftrace_event_id);

    std::string contents =
        ftrace_procfs->ReadEventFormat(event.group, event.name);
    FtraceEvent ftrace_event;
    if (contents.empty() || !ParseFtraceEvent(contents, &ftrace_event)) {
      continue;
    }

    event.ftrace_event_id = ftrace_event.id;

    if (!common_fields_processed) {
      common_fields_end =
          MergeFields(ftrace_event.common_fields, &common_fields, event.name);
      common_fields_processed = true;
    }

    uint16_t fields_end =
        MergeFields(ftrace_event.fields, &event.fields, event.name);

    event.size = std::max<uint16_t>(fields_end, common_fields_end);
  }

  events.erase(std::remove_if(events.begin(), events.end(),
                              [](const Event& event) {
                                return event.proto_field_id == 0 ||
                                       event.ftrace_event_id == 0;
                              }),
               events.end());

  auto table = std::unique_ptr<ProtoTranslationTable>(
      new ProtoTranslationTable(events, std::move(common_fields)));
  return table;
}

ProtoTranslationTable::ProtoTranslationTable(const std::vector<Event>& events,
                                             std::vector<Field> common_fields)
    : events_(BuildEventsVector(events)),
      largest_id_(events_.size() - 1),
      common_fields_(std::move(common_fields)) {
  for (const Event& event : events) {
    name_to_event_[event.name] = &events_.at(event.ftrace_event_id);
  }
}

ProtoTranslationTable::~ProtoTranslationTable() = default;

}  // namespace perfetto
<|endoftext|>


<commit_before>/*
* This file is part of the Gluon project.
* Copyright (C) 2009 Sacha Schutz <istdasklar@free.fr>
* Copyright (C) 2009 Guillaume Martres <smarter@ubuntu.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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING.  If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/

#include "kalsound.h"
#include "kalbuffer.h"
#include <sndfile.h>

#include <KDE/KApplication>
#include <KDE/KDebug>

#include "kalengine.h"

class KALSoundPrivate
{
public:
    KALBuffer *buffer;
    ALuint source;
    ALfloat x;
    ALfloat y;
    ALfloat z;
    ALfloat volume;
    ALfloat pitch;
};

KALSound::KALSound(QObject * parent)
           :QObject(parent),
           d(new KALSoundPrivate)
{
    init();
    d->buffer= new KALBuffer;
}
KALSound::KALSound(const QString &soundFile, QObject *parent)
    : QObject(parent),
    d(new KALSoundPrivate)
{
    init();
    d->buffer = new KALBuffer;
    load(soundFile);
}

KALSound::KALSound(KALBuffer *buffer, QObject *parent)
    :QObject(parent),
    d(new KALSoundPrivate)
{
    init();
    load(buffer);
}

KALSound::KALSound(ALuint buffer, QObject *parent)
    :QObject(parent),
    d(new KALSoundPrivate)
{
    init();
    load(buffer);
}

KALSound::~KALSound()
{
    alDeleteSources(1, &d->source);
    delete d;
}
void KALSound::load (const QString &soundFile)
{
    d->buffer->setBuffer(soundFile);
    setupSource();
}

void KALSound::load(KALBuffer * buffer) {
    d->buffer = buffer;
    setupSource();
}
void KALSound::load(ALuint buffer) {
    d->buffer = new KALBuffer(buffer);
    setupSource();
}

void KALSound::init()
{
    d->source=0;
    d->x=0;
    d->y=0;
    d->z=0;
    d->volume=0;
    d->pitch=0;
}

void KALSound::setupSource()
{
    alGenSources(1, &d->source);  // Generate the source to play the buffer with
    alSourcei(d->source, AL_BUFFER, d->buffer->buffer());  // Attach source to buffer

    if (alGetError() != AL_NO_ERROR) {
        kDebug() << "Could not process sound while generating source:" << alGetError();
        return;
    }

    if (!d->source) {
        kDebug() << "Could not process sound: generated source empty.";
        return;
    }
}
ALfloat KALSound::elapsedTime()const
{
    ALfloat seconds = 0.f;
    alGetSourcef(d->source, AL_SEC_OFFSET, &seconds);
    return seconds;
}

ALint KALSound::status()const
{
    ALint status;
    alGetSourcei(d->source, AL_SOURCE_STATE, &status);
    return status;
}

void KALSound::setLoop(bool enabled)
{
    alSourcei(d->source, AL_LOOPING, enabled);

}

ALfloat KALSound::x()const
{
    return d->x;
}

ALfloat KALSound::y()const
{
    return d->y;
}

ALfloat KALSound::z()const
{
    return d->z;
}

ALfloat KALSound::volume()const
{
    return d->volume;
}

ALfloat KALSound::pitch()const
{
    return d->pitch;
}

void KALSound::setPosition(ALfloat x, ALfloat y, ALfloat z)
{
    d->x = x;
    d->y = y;
    d->z = z;

    ALfloat listenerPosition[] = { x, y, z };
    alSourcefv(d->source, AL_POSITION, listenerPosition);
}

void KALSound::setVolume(ALfloat volume)
{
    d->volume = volume;
    alSourcef(d->source, AL_GAIN, volume);
}

void KALSound::setPitch(ALfloat pitch)
{
    d->pitch = pitch;
    alSourcef(d->source, AL_PITCH, pitch);
}

void KALSound::play()
{
    alSourcePlay(d->source);
}

void KALSound::pause()
{
    alSourcePause(d->source);
}

void KALSound::stop()
{
    alSourceStop(d->source);
}

void KALSound::rewind()
{
    alSourceRewind(d->source);
}

void KALSound::setMinVolume(ALfloat min)
{
    alSourcef(d->source, AL_MIN_GAIN, min);
}

void KALSound::setMaxVolume(ALfloat max)
{
    alSourcef(d->source, AL_MAX_GAIN, max);
}

void KALSound::setVelocity(ALfloat vx, ALfloat vy, ALfloat vz)
{
    ALfloat velocity[] = { vx, vy, vz };
    alSourcefv(d->source, AL_VELOCITY, velocity);
}

void KALSound::setDirection(ALfloat dx, ALfloat dy, ALfloat dz)
{
    ALfloat direction[] = { dx, dy, dz };
    alSourcefv(d->source, AL_POSITION, direction);
}

void KALSound::setTimePosition(ALfloat time)
{
    alSourcef(d->source, AL_SEC_OFFSET, time);

}
ALfloat KALSound::duration()const
{
    return d->buffer->duration();
}
ALuint  KALSound::source()const {
    return d->source;
}
<commit_msg>remove unused kapplication include<commit_after>/*
* This file is part of the Gluon project.
* Copyright (C) 2009 Sacha Schutz <istdasklar@free.fr>
* Copyright (C) 2009 Guillaume Martres <smarter@ubuntu.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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING.  If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/

#include "kalsound.h"
#include "kalbuffer.h"
#include <sndfile.h>

#include <KDE/KDebug>

#include "kalengine.h"

class KALSoundPrivate
{
public:
    KALBuffer *buffer;
    ALuint source;
    ALfloat x;
    ALfloat y;
    ALfloat z;
    ALfloat volume;
    ALfloat pitch;
};

KALSound::KALSound(QObject * parent)
           :QObject(parent),
           d(new KALSoundPrivate)
{
    init();
    d->buffer= new KALBuffer;
}
KALSound::KALSound(const QString &soundFile, QObject *parent)
    : QObject(parent),
    d(new KALSoundPrivate)
{
    init();
    d->buffer = new KALBuffer;
    load(soundFile);
}

KALSound::KALSound(KALBuffer *buffer, QObject *parent)
    :QObject(parent),
    d(new KALSoundPrivate)
{
    init();
    load(buffer);
}

KALSound::KALSound(ALuint buffer, QObject *parent)
    :QObject(parent),
    d(new KALSoundPrivate)
{
    init();
    load(buffer);
}

KALSound::~KALSound()
{
    alDeleteSources(1, &d->source);
    delete d;
}
void KALSound::load (const QString &soundFile)
{
    d->buffer->setBuffer(soundFile);
    setupSource();
}

void KALSound::load(KALBuffer * buffer) {
    d->buffer = buffer;
    setupSource();
}
void KALSound::load(ALuint buffer) {
    d->buffer = new KALBuffer(buffer);
    setupSource();
}

void KALSound::init()
{
    d->source=0;
    d->x=0;
    d->y=0;
    d->z=0;
    d->volume=0;
    d->pitch=0;
}

void KALSound::setupSource()
{
    alGenSources(1, &d->source);  // Generate the source to play the buffer with
    alSourcei(d->source, AL_BUFFER, d->buffer->buffer());  // Attach source to buffer

    if (alGetError() != AL_NO_ERROR) {
        kDebug() << "Could not process sound while generating source:" << alGetError();
        return;
    }

    if (!d->source) {
        kDebug() << "Could not process sound: generated source empty.";
        return;
    }
}
ALfloat KALSound::elapsedTime()const
{
    ALfloat seconds = 0.f;
    alGetSourcef(d->source, AL_SEC_OFFSET, &seconds);
    return seconds;
}

ALint KALSound::status()const
{
    ALint status;
    alGetSourcei(d->source, AL_SOURCE_STATE, &status);
    return status;
}

void KALSound::setLoop(bool enabled)
{
    alSourcei(d->source, AL_LOOPING, enabled);

}

ALfloat KALSound::x()const
{
    return d->x;
}

ALfloat KALSound::y()const
{
    return d->y;
}

ALfloat KALSound::z()const
{
    return d->z;
}

ALfloat KALSound::volume()const
{
    return d->volume;
}

ALfloat KALSound::pitch()const
{
    return d->pitch;
}

void KALSound::setPosition(ALfloat x, ALfloat y, ALfloat z)
{
    d->x = x;
    d->y = y;
    d->z = z;

    ALfloat listenerPosition[] = { x, y, z };
    alSourcefv(d->source, AL_POSITION, listenerPosition);
}

void KALSound::setVolume(ALfloat volume)
{
    d->volume = volume;
    alSourcef(d->source, AL_GAIN, volume);
}

void KALSound::setPitch(ALfloat pitch)
{
    d->pitch = pitch;
    alSourcef(d->source, AL_PITCH, pitch);
}

void KALSound::play()
{
    alSourcePlay(d->source);
}

void KALSound::pause()
{
    alSourcePause(d->source);
}

void KALSound::stop()
{
    alSourceStop(d->source);
}

void KALSound::rewind()
{
    alSourceRewind(d->source);
}

void KALSound::setMinVolume(ALfloat min)
{
    alSourcef(d->source, AL_MIN_GAIN, min);
}

void KALSound::setMaxVolume(ALfloat max)
{
    alSourcef(d->source, AL_MAX_GAIN, max);
}

void KALSound::setVelocity(ALfloat vx, ALfloat vy, ALfloat vz)
{
    ALfloat velocity[] = { vx, vy, vz };
    alSourcefv(d->source, AL_VELOCITY, velocity);
}

void KALSound::setDirection(ALfloat dx, ALfloat dy, ALfloat dz)
{
    ALfloat direction[] = { dx, dy, dz };
    alSourcefv(d->source, AL_POSITION, direction);
}

void KALSound::setTimePosition(ALfloat time)
{
    alSourcef(d->source, AL_SEC_OFFSET, time);

}
ALfloat KALSound::duration()const
{
    return d->buffer->duration();
}
ALuint  KALSound::source()const {
    return d->source;
}
<|endoftext|>


<commit_before>/*
 * NotebookWorkingDir.cpp
 *
 * Copyright (C) 2009-16 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "SessionRmdNotebook.hpp"
#include "NotebookWorkingDir.hpp"

#include <r/RExec.hpp>

#include <core/FilePath.hpp>

#include <session/SessionSourceDatabase.hpp>
#include <session/SessionModuleContext.hpp>

using namespace rstudio::core;

namespace rstudio {
namespace session {
namespace modules {
namespace rmarkdown {
namespace notebook {

DirCapture::DirCapture():
   warned_(false)
{
}

DirCapture::~DirCapture()
{
}

Error DirCapture::connectDir(const std::string& docId,
                             const core::FilePath& workingDir)
{
   if (workingDir.exists())
   {
      // prefer manually specified working directory
      workingDir_ = workingDir;
   }
   else
   {
      // no manually specified dir; use working directory to doc path, if it
      // has one
      std::string docPath;
      source_database::getPath(docId, &docPath);
      if (!docPath.empty())
      {
         workingDir_ = module_context::resolveAliasedPath(docPath).parent();
      }
   }

   if (!workingDir_.empty())
   {
      // if we have a working directory, switch to it, and save directory we're
      // changing from (so we can detect changes)
      FilePath currentDir = FilePath::safeCurrentPath(workingDir_);
      if (currentDir != workingDir_)
      {
         Error error = FilePath::makeCurrent(workingDir_.absolutePath());
         if (error)
            return error;
      }
      prevWorkingDir_ = currentDir.absolutePath();
   }

   NotebookCapture::connect();

   return Success();
}

void DirCapture::disconnect()
{
   // restore working directory, if we saved one
   if (connected() && !prevWorkingDir_.empty())
   {
      Error error = FilePath::makeCurrent(prevWorkingDir_);
      if (error)
         LOG_ERROR(error);
   }
   NotebookCapture::disconnect();
}

void DirCapture::onExprComplete()
{
   if (!warned_ && !workingDir_.empty())
   {
      // raise a warning when changing a working directory inside the notebook
      // (this leads to unexpected behavior)
      FilePath currentDir = FilePath::safeCurrentPath(workingDir_);
      if (!currentDir.isEquivalentTo(workingDir_))
      {
         r::exec::warning("The working directory was changed to " +
               currentDir.absolutePath() + " inside a notebook chunk. The "
               "working directory will be reset when the chunk is finished "
               "running. Use the knitr root.dir option in the setup chunk "
               "to change the working directory for notebook chunks.");

         // don't show warning more than once per chunk
         warned_ = true;
      }
   }
}

} // namespace notebook
} // namespace rmarkdown
} // namespace modules
} // namespace session
} // namespace rstudio

<commit_msg>include newline in notebook working dir message<commit_after>/*
 * NotebookWorkingDir.cpp
 *
 * Copyright (C) 2009-16 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "SessionRmdNotebook.hpp"
#include "NotebookWorkingDir.hpp"

#include <r/RExec.hpp>

#include <core/FilePath.hpp>

#include <session/SessionSourceDatabase.hpp>
#include <session/SessionModuleContext.hpp>

using namespace rstudio::core;

namespace rstudio {
namespace session {
namespace modules {
namespace rmarkdown {
namespace notebook {

DirCapture::DirCapture():
   warned_(false)
{
}

DirCapture::~DirCapture()
{
}

Error DirCapture::connectDir(const std::string& docId,
                             const core::FilePath& workingDir)
{
   if (workingDir.exists())
   {
      // prefer manually specified working directory
      workingDir_ = workingDir;
   }
   else
   {
      // no manually specified dir; use working directory to doc path, if it
      // has one
      std::string docPath;
      source_database::getPath(docId, &docPath);
      if (!docPath.empty())
      {
         workingDir_ = module_context::resolveAliasedPath(docPath).parent();
      }
   }

   if (!workingDir_.empty())
   {
      // if we have a working directory, switch to it, and save directory we're
      // changing from (so we can detect changes)
      FilePath currentDir = FilePath::safeCurrentPath(workingDir_);
      if (currentDir != workingDir_)
      {
         Error error = FilePath::makeCurrent(workingDir_.absolutePath());
         if (error)
            return error;
      }
      prevWorkingDir_ = currentDir.absolutePath();
   }

   NotebookCapture::connect();

   return Success();
}

void DirCapture::disconnect()
{
   // restore working directory, if we saved one
   if (connected() && !prevWorkingDir_.empty())
   {
      Error error = FilePath::makeCurrent(prevWorkingDir_);
      if (error)
         LOG_ERROR(error);
   }
   NotebookCapture::disconnect();
}

void DirCapture::onExprComplete()
{
   if (!warned_ && !workingDir_.empty())
   {
      // raise a warning when changing a working directory inside the notebook
      // (this leads to unexpected behavior)
      FilePath currentDir = FilePath::safeCurrentPath(workingDir_);
      if (!currentDir.isEquivalentTo(workingDir_))
      {
         r::exec::warning("The working directory was changed to " +
               currentDir.absolutePath() + " inside a notebook chunk. The "
               "working directory will be reset when the chunk is finished "
               "running. Use the knitr root.dir option in the setup chunk "
               "to change the working directory for notebook chunks.\n");

         // don't show warning more than once per chunk
         warned_ = true;
      }
   }
}

} // namespace notebook
} // namespace rmarkdown
} // namespace modules
} // namespace session
} // namespace rstudio

<|endoftext|>


<commit_before>/// HEADER
#include "pointmatrix_to_pointcloud.h"

/// PROJECT
#include <csapex_point_cloud/point_cloud_message.h>
#include <csapex/model/connector_in.h>
#include <csapex/model/connector_out.h>
#include <utils_param/parameter_factory.h>
#include <csapex_vision/cv_mat_message.h>

/// SYSTEM
#include <csapex/utility/register_apex_plugin.h>
#include <pcl/point_types.h>
#include <pcl/conversions.h>

CSAPEX_REGISTER_CLASS(csapex::PointmatrixToPointcloud, csapex::Node)

using namespace csapex;
using namespace csapex::connection_types;

namespace implementation {
inline void convert(const cv::Mat &matrix, pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud)
{
    if(matrix.type() != CV_32FC3) {
        throw std::runtime_error("3Channel float matrix required!");
    }

    cloud.reset(new pcl::PointCloud<pcl::PointXYZ>);
    cloud->height = matrix.rows;
    cloud->width  = matrix.cols;

    for(int i = 0 ; i < matrix.rows ; ++i) {
        for(int j = 0 ; j < matrix.cols ; ++j) {
            pcl::PointXYZ pt;
            pt.x = matrix.at<float>(i, (j * 3 + 0));
            pt.y = matrix.at<float>(i, (j * 3 + 1));
            pt.z = matrix.at<float>(i, (j * 3 + 2));
            cloud->push_back(pt);
        }
    }
}
}

PointmatrixToPointcloud::PointmatrixToPointcloud()
{
}

void PointmatrixToPointcloud::process()
{
    CvMatMessage::Ptr in = input_->getMessage<connection_types::CvMatMessage>();
    PointCloudMessage::Ptr out(new PointCloudMessage);
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud;

    implementation::convert(in->value, cloud);
    out->value = cloud;
    output_->publish(out);
}

void PointmatrixToPointcloud::setup()
{
    setSynchronizedInputs(true);
    input_  = addInput<CvMatMessage>("Point Matrix");
    output_ = addOutput<PointCloudMessage>("PointCloud");
}
<commit_msg>fixed bug: with and height of pointcloud has to be asigned ater the points are pushed in the cloud other wise height will be 1<commit_after>/// HEADER
#include "pointmatrix_to_pointcloud.h"

/// PROJECT
#include <csapex_point_cloud/point_cloud_message.h>
#include <csapex/model/connector_in.h>
#include <csapex/model/connector_out.h>
#include <utils_param/parameter_factory.h>
#include <csapex_vision/cv_mat_message.h>

/// SYSTEM
#include <csapex/utility/register_apex_plugin.h>
#include <pcl/point_types.h>
#include <pcl/conversions.h>

CSAPEX_REGISTER_CLASS(csapex::PointmatrixToPointcloud, csapex::Node)

using namespace csapex;
using namespace csapex::connection_types;

namespace implementation {
inline void convert(const cv::Mat &matrix, pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud)
{
    if(matrix.type() != CV_32FC3) {
        throw std::runtime_error("3Channel float matrix required!");
    }

    cloud.reset(new pcl::PointCloud<pcl::PointXYZ>);

    for(int i = 0 ; i < matrix.rows ; ++i) {
        for(int j = 0 ; j < matrix.cols ; ++j) {
            pcl::PointXYZ pt;
            pt.x = matrix.at<float>(i, (j * 3 + 0));
            pt.y = matrix.at<float>(i, (j * 3 + 1));
            pt.z = matrix.at<float>(i, (j * 3 + 2));
            cloud->push_back(pt);
        }
    }

    cloud->height = matrix.rows;
    cloud->width  = matrix.cols;
    cloud->is_dense = false;

}
}

PointmatrixToPointcloud::PointmatrixToPointcloud()
{
}

void PointmatrixToPointcloud::process()
{
    CvMatMessage::Ptr in = input_->getMessage<connection_types::CvMatMessage>();
    PointCloudMessage::Ptr out(new PointCloudMessage);
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud;

    implementation::convert(in->value, cloud);
    out->value = cloud;
    output_->publish(out);
}

void PointmatrixToPointcloud::setup()
{
    setSynchronizedInputs(true);
    input_  = addInput<CvMatMessage>("Point Matrix");
    output_ = addOutput<PointCloudMessage>("PointCloud");
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: schemabuilder.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: hr $ $Date: 2003-03-19 16:18:49 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef CONFIGMGR_BACKEND_SCHEMABUILDER_HXX
#define CONFIGMGR_BACKEND_SCHEMABUILDER_HXX

#ifndef CONFIGMGR_BACKEND_MERGEDCOMPONENTDATA_HXX
#include "mergedcomponentdata.hxx"
#endif
#ifndef CONFIGMGR_BACKEND_COMPONENTDATAHELPER_HXX
#include "componentdatahelper.hxx"
#endif
#ifndef CONFIGMGR_BACKEND_MERGEDDATAPROVIDER_HXX
#include "mergeddataprovider.hxx"
#endif

#include <drafts/com/sun/star/configuration/backend/XSchemaHandler.hpp>

#ifndef _CPPUHELPER_IMPLBASE1_HXX_
#include <cppuhelper/implbase1.hxx>
#endif

namespace configmgr
{
// -----------------------------------------------------------------------------
    class OTreeNodeFactory;
// -----------------------------------------------------------------------------
    namespace backend
    {
// -----------------------------------------------------------------------------
        namespace uno       = ::com::sun::star::uno;
        namespace lang      = ::com::sun::star::lang;
        namespace beans     = ::com::sun::star::beans;
        namespace container = ::com::sun::star::container;

        namespace backenduno = ::drafts::com::sun::star::configuration::backend;

// -----------------------------------------------------------------------------

        typedef ::cppu::WeakImplHelper1<backenduno::XSchemaHandler> SchemaBuilder_Base;

        class SchemaBuilder
        :   public SchemaBuilder_Base
        {
        public:
            SchemaBuilder( const OUString& aExpectedComponentName, ITemplateDataProvider* aTemplateProvider = NULL );
            virtual ~SchemaBuilder();

        // checking the result
            bool isDone() const { return m_aContext.isDone(); }

            MergedComponentData &       result();
            MergedComponentData const & result() const;

        // XSchemaHandler
        public:
            virtual void SAL_CALL
                startSchema(  )
                    throw (MalformedDataException, uno::RuntimeException);

            virtual void SAL_CALL
                endSchema(  )
                    throw (MalformedDataException, uno::RuntimeException);

            virtual void SAL_CALL
                importComponent( const OUString& aName )
                    throw (MalformedDataException, container::NoSuchElementException, lang::IllegalArgumentException, uno::RuntimeException);

            virtual void SAL_CALL
                startComponent( const OUString& aName )
                    throw (MalformedDataException, container::ElementExistException, lang::IllegalArgumentException, lang::NoSupportException, uno::RuntimeException);

            virtual void SAL_CALL
                endComponent(  )
                    throw (MalformedDataException, lang::NoSupportException, uno::RuntimeException);

            virtual void SAL_CALL
                startGroupTemplate( const TemplateIdentifier& aTemplate, sal_Int16 aAttributes )
                    throw (MalformedDataException, container::ElementExistException, lang::IllegalArgumentException, lang::NoSupportException, uno::RuntimeException);

            virtual void SAL_CALL
                startSetTemplate( const TemplateIdentifier& aTemplate, sal_Int16 aAttributes, const TemplateIdentifier& aItemType )
                    throw (MalformedDataException, container::ElementExistException, container::NoSuchElementException, lang::IllegalArgumentException, lang::NoSupportException, uno::RuntimeException);

            virtual void SAL_CALL
                endTemplate(  )
                    throw (MalformedDataException, lang::NoSupportException, uno::RuntimeException);

            virtual void SAL_CALL
                startGroup( const OUString& aName, sal_Int16 aAttributes )
                    throw (MalformedDataException, container::ElementExistException, lang::IllegalArgumentException, uno::RuntimeException);

            virtual void SAL_CALL
                startSet( const OUString& aName, sal_Int16 aAttributes, const TemplateIdentifier& aItemType )
                    throw (MalformedDataException, container::ElementExistException, container::NoSuchElementException, lang::IllegalArgumentException, uno::RuntimeException);

            virtual void SAL_CALL
                endNode(  )
                    throw (MalformedDataException, uno::RuntimeException);

            virtual void SAL_CALL
                addProperty( const OUString& aName, sal_Int16 aAttributes, const uno::Type& aType )
                    throw (MalformedDataException, beans::PropertyExistException, beans::IllegalTypeException, lang::IllegalArgumentException, uno::RuntimeException);

            virtual void SAL_CALL
                addPropertyWithDefault( const OUString& aName, sal_Int16 aAttributes, const uno::Any& aDefaultValue )
                    throw (MalformedDataException, beans::PropertyExistException, beans::IllegalTypeException, lang::IllegalArgumentException, uno::RuntimeException);

            virtual void SAL_CALL
                addInstance( const OUString& aName, const TemplateIdentifier& aTemplate )
                    throw (MalformedDataException, container::ElementExistException, container::NoSuchElementException, lang::IllegalArgumentException, uno::RuntimeException);

            virtual void SAL_CALL
                addItemType( const TemplateIdentifier& aItemType )
                    throw (MalformedDataException, container::NoSuchElementException, lang::IllegalArgumentException, uno::RuntimeException);

        private:
            static node::Attributes getComponentRootAttributes();
            static node::Attributes getTemplateBaseAttributes();
            node::Attributes makePropertyAttributes(sal_Int16 aSchemaAttributes);

            bool isExtensible(sal_Int16 aSchemaAttributes);

            void substituteInstances();
        private:
            MergedComponentData     m_aData;
            DataBuilderContext      m_aContext;
            ComponentDataFactory    m_aFactory;
            ITemplateDataProvider *  m_aTemplateProvider;
        };
// -----------------------------------------------------------------------------

    } // namespace backend
// -----------------------------------------------------------------------------

} // namespace configmgr
#endif

<commit_msg>INTEGRATION: CWS configapi01 (1.3.10); FILE MERGED 2003/04/10 15:47:11 jb 1.3.10.1: #1077715# Move configuration backend API out of drafts; adjust to API changes<commit_after>/*************************************************************************
 *
 *  $RCSfile: schemabuilder.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2003-04-17 13:18:07 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef CONFIGMGR_BACKEND_SCHEMABUILDER_HXX
#define CONFIGMGR_BACKEND_SCHEMABUILDER_HXX

#ifndef CONFIGMGR_BACKEND_MERGEDCOMPONENTDATA_HXX
#include "mergedcomponentdata.hxx"
#endif
#ifndef CONFIGMGR_BACKEND_COMPONENTDATAHELPER_HXX
#include "componentdatahelper.hxx"
#endif
#ifndef CONFIGMGR_BACKEND_MERGEDDATAPROVIDER_HXX
#include "mergeddataprovider.hxx"
#endif

#ifndef _COM_SUN_STAR_CONFIGURATION_BACKEND_XSCHEMAHANDLER_HPP_
#include <com/sun/star/configuration/backend/XSchemaHandler.hpp>
#endif

#ifndef _CPPUHELPER_IMPLBASE1_HXX_
#include <cppuhelper/implbase1.hxx>
#endif

namespace configmgr
{
// -----------------------------------------------------------------------------
    class OTreeNodeFactory;
// -----------------------------------------------------------------------------
    namespace backend
    {
// -----------------------------------------------------------------------------
        namespace uno       = ::com::sun::star::uno;
        namespace lang      = ::com::sun::star::lang;

        namespace backenduno = ::com::sun::star::configuration::backend;

        using backenduno::MalformedDataException;
// -----------------------------------------------------------------------------

        typedef ::cppu::WeakImplHelper1<backenduno::XSchemaHandler> SchemaBuilder_Base;

        class SchemaBuilder
        :   public SchemaBuilder_Base
        {
        public:
            SchemaBuilder( const OUString& aExpectedComponentName, ITemplateDataProvider* aTemplateProvider = NULL );
            virtual ~SchemaBuilder();

        // checking the result
            bool isDone() const { return m_aContext.isDone(); }

            MergedComponentData &       result();
            MergedComponentData const & result() const;

        // XSchemaHandler
        public:
            virtual void SAL_CALL
                startSchema(  )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                endSchema(  )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                importComponent( const OUString& aName )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                startComponent( const OUString& aName )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                endComponent(  )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                startGroupTemplate( const TemplateIdentifier& aTemplate, sal_Int16 aAttributes )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                startSetTemplate( const TemplateIdentifier& aTemplate, sal_Int16 aAttributes, const TemplateIdentifier& aItemType )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                endTemplate(  )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                startGroup( const OUString& aName, sal_Int16 aAttributes )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                startSet( const OUString& aName, sal_Int16 aAttributes, const TemplateIdentifier& aItemType )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                endNode(  )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                addProperty( const OUString& aName, sal_Int16 aAttributes, const uno::Type& aType )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                addPropertyWithDefault( const OUString& aName, sal_Int16 aAttributes, const uno::Any& aDefaultValue )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                addInstance( const OUString& aName, const TemplateIdentifier& aTemplate )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

            virtual void SAL_CALL
                addItemType( const TemplateIdentifier& aItemType )
                    throw (MalformedDataException, lang::WrappedTargetException, uno::RuntimeException);

        private:
            static node::Attributes getComponentRootAttributes();
            static node::Attributes getTemplateBaseAttributes();
            node::Attributes makePropertyAttributes(sal_Int16 aSchemaAttributes);

            bool isExtensible(sal_Int16 aSchemaAttributes);

            void substituteInstances();
        private:
            MergedComponentData     m_aData;
            DataBuilderContext      m_aContext;
            ComponentDataFactory    m_aFactory;
            ITemplateDataProvider *  m_aTemplateProvider;
        };
// -----------------------------------------------------------------------------

    } // namespace backend
// -----------------------------------------------------------------------------

} // namespace configmgr
#endif

<|endoftext|>


<commit_before>#ifdef _MSC_VER
#include <filesystem>
#endif
#include <map>
#include <babylon/core/string.h>
#include <imgui_utils/icons_font_awesome_5.h>
#include <imgui_utils/imgui_utils.h>
#include <babylon/imgui_babylon/sample_list_page.h>
#include <babylon/interfaces/irenderable_scene.h>

#include <imgui.h>

#include <babylon/inspector/inspector.h>
#include <babylon/samples/samples_index.h>

#ifdef _WIN32
#include <windows.h>
#endif // _WIN32

namespace
{
std::string to_snake_case(const std::string &sPascalCase)
{
  std::stringstream ss;
  bool first = true;
  for (auto c : sPascalCase)
  {
    if (std::tolower(c) != c)
    {
      if (!first)
        ss << "_";
      ss << static_cast<unsigned char>(std::tolower(c));
    }
    else
      ss << c;
    first = false;
  }
  return ss.str();
}

const std::string screenshotsFolderCurrent = "../../../assets/screenshots/samples_current/";
const std::string screenshotsFolderOriginal = "../../../assets/screenshots/samples/";

} // end anonymous namespace

namespace BABYLON {

namespace
{
  void openBrowser(const std::string &url)
  {
#ifndef _WIN32
    std::string cmd = std::string("open ") + url;
    system(cmd.c_str());
#else
    ShellExecute(0, 0, url.c_str(), 0, 0, SW_SHOW);
#endif
  }
  void openFile(const std::string &filename)
  {
#ifndef _WIN32
    std::string cmd = std::string("open ") + filename;
    system(cmd.c_str());
#else
    std::string canonical_path = std::filesystem::canonical(std::filesystem::path(filename)).string();
    ShellExecute(0, 0, canonical_path.c_str(), 0, 0, SW_SHOW);
#endif
  }
}

using namespace BABYLON::Samples;

class SampleListPageImpl
{
public:
  using CategoryName = std::string;
  using SampleName = std::string;

  SampleListPageImpl()
  {
    for (const std::string & sample : _samplesIndex.getSampleNames())
      _samplesInfos[sample] = _samplesIndex.getSampleInfo(sample);
    fillMatchingSamples();
  }

  void render()
  {
    render_filter();
    ImGui::Checkbox("Show original screenshots", &_showOriginalScreenshots);
    ImGui::SameLine();
    ImGui::Checkbox("Show current screenshots", &_showCurrentScreenshots);
    ImGui::Separator();
    render_list();
    ImGui::NewLine();
    ImGui::Separator();
    ImGui::NewLine();
  }

  SampleListPage::CallbackNewRenderableScene OnNewRenderableScene;

private:
  void render_filter()
  {
    bool changed = false;
    ImGui::Text("Filter");
    if (ImGui::InputText_String("", _query.query))
      changed = true;

    if (ImGui::Checkbox("Include disabled", &_query.includeDisabled))
      changed = true;
    ImGui::SameLine();
    if (ImGui::Checkbox("Include failing", &_query.includeFailures))
      changed = true;
    ImGui::SameLine();
    if (ImGui::Checkbox("Only failing", &_query.onlyFailures))
      changed = true;

    if (changed)
      fillMatchingSamples();
  }

  void render_list()
  {
    enum class CollapseMode
    {
      None,
      CollapseAll,
      ExpandAll
    };
    CollapseMode collapseMode = CollapseMode::None;
    if (ImGui::Button("Collapse All"))
      collapseMode = CollapseMode::CollapseAll;
    ImGui::SameLine();
    if (ImGui::Button("Expand All"))
      collapseMode = CollapseMode::ExpandAll;

    ImGui::BeginChild("Child1");
    for (const auto & kv : _matchingSamples)
    {
      CategoryName category = kv.first;
      auto samples = kv.second;
      if (!samples.empty())
      {
        std::string header = category + " (" + std::to_string(samples.size()) + ")";
        if (collapseMode == CollapseMode::CollapseAll)
          ImGui::SetNextItemOpen(false);
        if (collapseMode == CollapseMode::ExpandAll)
          ImGui::SetNextItemOpen(true);
        if (ImGui::CollapsingHeader(header.c_str(), ImGuiTreeNodeFlags_DefaultOpen))
        {
          for (const std::string & sample : samples)
          {
            //ImGui::Text("%s", sample.c_str());
            guiOneSample(sample);
            ImGui::Separator();
          }
        }
      }
    }
    ImGui::EndChild();

  }

  void guiOneSampleInfos(const std::string & sampleName)
  {
    const auto & sampleInfo = _samplesInfos.at(sampleName);

    std::string runLabel = std::string(ICON_FA_PLAY_CIRCLE " Run##") + sampleName;
    if (ImGui::Button(runLabel.c_str()))
    {
      if (OnNewRenderableScene)
      {
        BABYLON::ICanvas *dummyCanvas = nullptr;
        auto scene = _samplesIndex.createRenderableScene(sampleName, dummyCanvas);
        OnNewRenderableScene(std::move(scene));
      }
      if (Inspector::OnSampleChanged)
        Inspector::OnSampleChanged(sampleName);
    }

    std::string btnHeaderString = std::string(ICON_FA_EYE "##") + sampleInfo.HeaderFile;
    if (ImGui::Button(btnHeaderString.c_str()))
      openFile(sampleInfo.HeaderFile);
    ImGui::SameLine();
    ImGui::TextDisabled(".h  : %s", sampleInfo.HeaderFile.c_str());

    std::string btnSourceString = std::string(ICON_FA_EYE "##") + sampleInfo.SourceFile;
    if (ImGui::Button(btnSourceString.c_str()))
      openFile(sampleInfo.SourceFile);
    ImGui::SameLine();
    ImGui::TextDisabled(".cpp: %s", sampleInfo.SourceFile.c_str());

    if (!sampleInfo.Links.empty()) {
      for (auto link : sampleInfo.Links) {
        std::string btnUrlString = std::string(ICON_FA_EXTERNAL_LINK_ALT "##") + link;
        if (ImGui::Button(btnUrlString.c_str()))
          openBrowser(link);
        ImGui::SameLine();
        ImVec4 linkColor(0.5f, 0.5f, 0.95f, 1.f);
        ImGui::TextColored(linkColor, "%s", link.c_str());
      }
    }
  }

  void guiOneSample(const std::string &sampleName)
  {
    const auto & sampleInfo = _samplesInfos[sampleName];
    std::string currentScreenshotFile = screenshotsFolderCurrent + sampleName + ".jpg";
    std::string sample_snake = to_snake_case(sampleName);
    std::string originalScreenshotFile = screenshotsFolderOriginal + sample_snake + ".png";

    if (_showCurrentScreenshots)
    {
      ImGui::BeginGroup();
      ImGuiUtils::ImageFromFile(currentScreenshotFile);
      if (_showOriginalScreenshots && _showCurrentScreenshots)
        ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 0.7f), "Current(c++)");
      ImGui::EndGroup();
      ImGui::SameLine();
    }

    if (_showOriginalScreenshots)
    {
      ImGui::BeginGroup();
      ImGuiUtils::ImageFromFile(originalScreenshotFile);
      if (_showOriginalScreenshots && _showCurrentScreenshots)
        ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 0.7f), "Original(js)");
      ImGui::EndGroup();
      ImGui::SameLine();
    }

    ImGui::BeginGroup();
    ImGui::Text("%s", sampleName.c_str());
    ImGui::TextWrapped("%s", sampleInfo.Brief.c_str());
    auto failure = _samplesIndex.doesSampleFail(sampleName);
    if (failure)
    {
      ImGui::TextColored(ImVec4(0.9f, 0.4f, 0.3f, 1.f), "Failure: %s",
        SampleFailureReason_Str(failure.value()).c_str()
      );
    }
    guiOneSampleInfos(sampleName);
    ImGui::EndGroup();
    ImGui::SameLine();

  }

  bool doesSampleMatchQuery(const CategoryName & categoryName, const SampleName & sampleName)
  {
    std::vector<std::string> search_items = BABYLON::String::split(_query.query, ' ');

    bool doesMatch = true;

    {
      std::string all = BABYLON::String::toLowerCase(categoryName + " / " + sampleName);
      for (const auto &item : search_items)
        if (!BABYLON::String::contains(all, BABYLON::String::toLowerCase(item)))
          doesMatch = false;
    }

    if (!_query.includeDisabled)
      if (!_samplesIndex.isSampleEnabled(sampleName))
        doesMatch = false;

    if (_query.onlyFailures)
    {
      if (!_samplesIndex.doesSampleFail(sampleName))
        doesMatch = false;
    }
    else if (!_query.includeFailures)
      if (_samplesIndex.doesSampleFail(sampleName))
        doesMatch = false;

    return doesMatch;
  }

  void fillMatchingSamples()
  {
    _matchingSamples.clear();

    for (CategoryName category : _samplesIndex.getCategoryNames())
    {
      std::vector<SampleName> s;
      for (SampleName sample : _samplesIndex.getSampleNamesInCategory(category))
      {
        if (doesSampleMatchQuery(category, sample))
          s.push_back(sample);
        _matchingSamples[category] = s;
      }
    }
  }

  std::map<SampleName, SampleInfo> _samplesInfos;
  SamplesIndex _samplesIndex;
  std::map<CategoryName, std::vector<SampleName>> _matchingSamples;

  struct {
    std::string query = "";
    bool includeFailures = false;
    bool onlyFailures = false;
    bool includeDisabled = true;
  } _query;

  bool _showOriginalScreenshots = false;
  bool _showCurrentScreenshots = true;
};

SampleListPage::SampleListPage()
{
  pImpl = std::make_unique<SampleListPageImpl>();
}

SampleListPage::~SampleListPage() = default;

void SampleListPage::render()
{
  pImpl->OnNewRenderableScene = OnNewRenderableScene;
  pImpl->render();
}

} // end of namespace BABYLON
<commit_msg>sample_list_page : show relative file paths<commit_after>#ifdef _MSC_VER
#include <filesystem>
#endif
#include <map>
#include <babylon/core/string.h>
#include <babylon/core/filesystem.h>
#include <imgui_utils/icons_font_awesome_5.h>
#include <imgui_utils/imgui_utils.h>
#include <babylon/imgui_babylon/sample_list_page.h>
#include <babylon/interfaces/irenderable_scene.h>

#include <imgui.h>

#include <babylon/inspector/inspector.h>
#include <babylon/samples/samples_index.h>

#ifdef _WIN32
#include <windows.h>
#endif // _WIN32

namespace
{
std::string to_snake_case(const std::string &sPascalCase)
{
  std::stringstream ss;
  bool first = true;
  for (auto c : sPascalCase)
  {
    if (std::tolower(c) != c)
    {
      if (!first)
        ss << "_";
      ss << static_cast<unsigned char>(std::tolower(c));
    }
    else
      ss << c;
    first = false;
  }
  return ss.str();
}

const std::string screenshotsFolderCurrent = "../../../assets/screenshots/samples_current/";
const std::string screenshotsFolderOriginal = "../../../assets/screenshots/samples/";
const std::string repositoryPath = BABYLON::Filesystem::absolutePath("../../../");

std::string repositoryRelativePath(const std::string & path)
{
  std::string absPath = BABYLON::Filesystem::absolutePath(path);
  std::string fromRepo = BABYLON::String::removeSubstring(absPath, repositoryPath);
  return fromRepo;
}

} // end anonymous namespace

namespace BABYLON {

namespace
{
  void openBrowser(const std::string &url)
  {
#ifndef _WIN32
    std::string cmd = std::string("open ") + url;
    system(cmd.c_str());
#else
    ShellExecute(0, 0, url.c_str(), 0, 0, SW_SHOW);
#endif
  }
  void openFile(const std::string &filename)
  {
#ifndef _WIN32
    std::string cmd = std::string("open ") + filename;
    system(cmd.c_str());
#else
    std::string canonical_path = std::filesystem::canonical(std::filesystem::path(filename)).string();
    ShellExecute(0, 0, canonical_path.c_str(), 0, 0, SW_SHOW);
#endif
  }
}

using namespace BABYLON::Samples;

class SampleListPageImpl
{
public:
  using CategoryName = std::string;
  using SampleName = std::string;

  SampleListPageImpl()
  {
    for (const std::string & sample : _samplesIndex.getSampleNames())
      _samplesInfos[sample] = _samplesIndex.getSampleInfo(sample);
    fillMatchingSamples();
  }

  void render()
  {
    render_filter();
    ImGui::Checkbox("Show original screenshots", &_showOriginalScreenshots);
    ImGui::SameLine();
    ImGui::Checkbox("Show current screenshots", &_showCurrentScreenshots);
    ImGui::Separator();
    render_list();
    ImGui::NewLine();
    ImGui::Separator();
    ImGui::NewLine();
  }

  SampleListPage::CallbackNewRenderableScene OnNewRenderableScene;

private:
  void render_filter()
  {
    bool changed = false;
    ImGui::Text("Filter");
    if (ImGui::InputText_String("", _query.query))
      changed = true;

    if (ImGui::Checkbox("Include disabled", &_query.includeDisabled))
      changed = true;
    ImGui::SameLine();
    if (ImGui::Checkbox("Include failing", &_query.includeFailures))
      changed = true;
    ImGui::SameLine();
    if (ImGui::Checkbox("Only failing", &_query.onlyFailures))
      changed = true;

    if (changed)
      fillMatchingSamples();
  }

  void render_list()
  {
    enum class CollapseMode
    {
      None,
      CollapseAll,
      ExpandAll
    };
    CollapseMode collapseMode = CollapseMode::None;
    if (ImGui::Button("Collapse All"))
      collapseMode = CollapseMode::CollapseAll;
    ImGui::SameLine();
    if (ImGui::Button("Expand All"))
      collapseMode = CollapseMode::ExpandAll;

    ImGui::BeginChild("Child1");
    for (const auto & kv : _matchingSamples)
    {
      CategoryName category = kv.first;
      auto samples = kv.second;
      if (!samples.empty())
      {
        std::string header = category + " (" + std::to_string(samples.size()) + ")";
        if (collapseMode == CollapseMode::CollapseAll)
          ImGui::SetNextItemOpen(false);
        if (collapseMode == CollapseMode::ExpandAll)
          ImGui::SetNextItemOpen(true);
        if (ImGui::CollapsingHeader(header.c_str(), ImGuiTreeNodeFlags_DefaultOpen))
        {
          for (const std::string & sample : samples)
          {
            //ImGui::Text("%s", sample.c_str());
            guiOneSample(sample);
            ImGui::Separator();
          }
        }
      }
    }
    ImGui::EndChild();

  }

  void guiOneSampleInfos(const std::string & sampleName)
  {
    const auto & sampleInfo = _samplesInfos.at(sampleName);

    std::string runLabel = std::string(ICON_FA_PLAY_CIRCLE " Run##") + sampleName;
    if (ImGui::Button(runLabel.c_str()))
    {
      if (OnNewRenderableScene)
      {
        BABYLON::ICanvas *dummyCanvas = nullptr;
        auto scene = _samplesIndex.createRenderableScene(sampleName, dummyCanvas);
        OnNewRenderableScene(std::move(scene));
      }
      if (Inspector::OnSampleChanged)
        Inspector::OnSampleChanged(sampleName);
    }

    std::string btnHeaderString = std::string(ICON_FA_EYE "##") + sampleInfo.HeaderFile;
    if (ImGui::Button(btnHeaderString.c_str()))
      openFile(sampleInfo.HeaderFile);
    ImGui::SameLine();
    ImGui::TextDisabled(".h  : %s", repositoryRelativePath(sampleInfo.HeaderFile).c_str());

    std::string btnSourceString = std::string(ICON_FA_EYE "##") + sampleInfo.SourceFile;
    if (ImGui::Button(btnSourceString.c_str()))
      openFile(sampleInfo.SourceFile);
    ImGui::SameLine();
    ImGui::TextDisabled(".cpp: %s", repositoryRelativePath(sampleInfo.SourceFile).c_str());

    if (!sampleInfo.Links.empty()) {
      for (auto link : sampleInfo.Links) {
        std::string btnUrlString = std::string(ICON_FA_EXTERNAL_LINK_ALT "##") + link;
        if (ImGui::Button(btnUrlString.c_str()))
          openBrowser(link);
        ImGui::SameLine();
        ImVec4 linkColor(0.5f, 0.5f, 0.95f, 1.f);
        ImGui::TextColored(linkColor, "%s", link.c_str());
      }
    }
  }

  void guiOneSample(const std::string &sampleName)
  {
    const auto & sampleInfo = _samplesInfos[sampleName];
    std::string currentScreenshotFile = screenshotsFolderCurrent + sampleName + ".jpg";
    std::string sample_snake = to_snake_case(sampleName);
    std::string originalScreenshotFile = screenshotsFolderOriginal + sample_snake + ".png";

    if (_showCurrentScreenshots)
    {
      ImGui::BeginGroup();
      ImGuiUtils::ImageFromFile(currentScreenshotFile);
      if (_showOriginalScreenshots && _showCurrentScreenshots)
        ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 0.7f), "Current(c++)");
      ImGui::EndGroup();
      ImGui::SameLine();
    }

    if (_showOriginalScreenshots)
    {
      ImGui::BeginGroup();
      ImGuiUtils::ImageFromFile(originalScreenshotFile);
      if (_showOriginalScreenshots && _showCurrentScreenshots)
        ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 0.7f), "Original(js)");
      ImGui::EndGroup();
      ImGui::SameLine();
    }

    ImGui::BeginGroup();
    ImGui::Text("%s", sampleName.c_str());
    ImGui::TextWrapped("%s", sampleInfo.Brief.c_str());
    auto failure = _samplesIndex.doesSampleFail(sampleName);
    if (failure)
    {
      ImGui::TextColored(ImVec4(0.9f, 0.4f, 0.3f, 1.f), "Failure: %s",
        SampleFailureReason_Str(failure.value()).c_str()
      );
    }
    guiOneSampleInfos(sampleName);
    ImGui::EndGroup();
    ImGui::SameLine();

  }

  bool doesSampleMatchQuery(const CategoryName & categoryName, const SampleName & sampleName)
  {
    std::vector<std::string> search_items = BABYLON::String::split(_query.query, ' ');

    bool doesMatch = true;

    {
      std::string all = BABYLON::String::toLowerCase(categoryName + " / " + sampleName);
      for (const auto &item : search_items)
        if (!BABYLON::String::contains(all, BABYLON::String::toLowerCase(item)))
          doesMatch = false;
    }

    if (!_query.includeDisabled)
      if (!_samplesIndex.isSampleEnabled(sampleName))
        doesMatch = false;

    if (_query.onlyFailures)
    {
      if (!_samplesIndex.doesSampleFail(sampleName))
        doesMatch = false;
    }
    else if (!_query.includeFailures)
      if (_samplesIndex.doesSampleFail(sampleName))
        doesMatch = false;

    return doesMatch;
  }

  void fillMatchingSamples()
  {
    _matchingSamples.clear();

    for (CategoryName category : _samplesIndex.getCategoryNames())
    {
      std::vector<SampleName> s;
      for (SampleName sample : _samplesIndex.getSampleNamesInCategory(category))
      {
        if (doesSampleMatchQuery(category, sample))
          s.push_back(sample);
        _matchingSamples[category] = s;
      }
    }
  }

  std::map<SampleName, SampleInfo> _samplesInfos;
  SamplesIndex _samplesIndex;
  std::map<CategoryName, std::vector<SampleName>> _matchingSamples;

  struct {
    std::string query = "";
    bool includeFailures = false;
    bool onlyFailures = false;
    bool includeDisabled = true;
  } _query;

  bool _showOriginalScreenshots = false;
  bool _showCurrentScreenshots = true;
};

SampleListPage::SampleListPage()
{
  pImpl = std::make_unique<SampleListPageImpl>();
}

SampleListPage::~SampleListPage() = default;

void SampleListPage::render()
{
  pImpl->OnNewRenderableScene = OnNewRenderableScene;
  pImpl->render();
}

} // end of namespace BABYLON
<|endoftext|>