<commit_before>/*****************************************************************************
 * Licensed to Qualys, Inc. (QUALYS) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * QUALYS licenses this file to You 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.
 ****************************************************************************/

/**
 * @file
 * @brief IronBee++ — Engine (PLACEHOLDER)
 *
 * This is a placeholder for future functionality.  Do not use.
 *
 * @author Christopher Alfeld <calfeld@qualys.com>
 */

#ifndef __IBPP__ENGINE__
#define __IBPP__ENGINE__

#include <ironbeepp/common_semantics.hpp>
#include <iostream>

// IronBee C
typedef struct ib_engine_t ib_engine_t;

namespace IronBee {

/**
 * Const Engine; equivalent to a const pointer to ib_engine_t.
 *
 * Provides operators ==, !=, <, >, <=, >= and evaluation as a boolean for
 * singularity via CommonSemantics.
 *
 * See Engine for discussion of the engine.
 *
 * @sa Engine
 * @sa ironbeepp
 * @sa ib_engine_t
 * @nosubgrouping
 **/
class ConstEngine :
    public CommonSemantics<ConstEngine>
{
public:
    /**
     * Construct singular ConstEngine.
     *
     * All behavior of a singular ConstEngine is undefined except for
     * assignment, copying, comparison, and evaluate-as-bool.
     **/
    ConstEngine();

    /**
     * @name C Interoperability
     * Methods to access underlying C types.
     **/
    ///@{

    //! const ib_engine_t accessor.
    // Intentionally inlined.
    const ib_engine_t* ib() const
    {
        return m_ib;
    }

    //! Construct Engine from ib_engine_t.
    explicit
    ConstEngine(const ib_engine_t* ib_engine);

    ///@}

private:
    const ib_engine_t* m_ib;
};

/**
 * Engine; equivalent to a pointer to ib_engine_t.
 *
 * An Engine can be treated as a ConstEngine.  See @ref ironbeepp for
 * details on IronBee++ object semantics.
 *
 * XXX
 *
 * @sa ironbeepp
 * @sa ib_engine_t
 * @sa ConstEngine
 * @nosubgrouping
 **/
class Engine :
    public ConstEngine
{
public:
    /**
     * Remove the constness of a ConstEngine.
     *
     * @warning This is as dangerous as a @c const_cast, use carefully.
     *
     * @param[in] bs ConstEngine to remove const from.
     * @returns Engine pointing to same underlying byte string as @a bs.
     **/
    static Engine remove_const(ConstEngine engine);

    /**
     * Construct singular Engine.
     *
     * All behavior of a singular Engine is undefined except for
     * assignment, copying, comparison, and evaluate-as-bool.
     **/
    Engine();

    /**
     * @name C Interoperability
     * Methods to access underlying C types.
     **/
    ///@{

    //! const ib_engine_t accessor.
    // Intentionally inlined.
    ib_engine_t* ib() const
    {
        return m_ib;
    }

    //! Construct Engine from ib_engine_t.
    explicit
    Engine(ib_engine_t* ib_engine);

    ///@}

private:
    ib_engine_t* m_ib;
};

/**
 * Output operator for Engine.
 *
 * Outputs Engine[@e value] to @a o where @e value is replaced with
 * the value of the bytestring.
 *
 * @param[in] o           Ostream to output to.
 * @param[in] byte_string Engine to output.
 * @return @a o
 **/
std::ostream& operator<<(std::ostream& o, const ConstEngine& engine);

} // IronBee

#endif
<commit_msg>IronBee++/Engine: API documentation.<commit_after>/*****************************************************************************
 * Licensed to Qualys, Inc. (QUALYS) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * QUALYS licenses this file to You 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.
 ****************************************************************************/

/**
 * @file
 * @brief IronBee++ — Engine
 *
 * This code is under construction.  Do not use yet.
 *
 * @author Christopher Alfeld <calfeld@qualys.com>
 */

#ifndef __IBPP__ENGINE__
#define __IBPP__ENGINE__

#include <ironbeepp/common_semantics.hpp>
#include <iostream>

// IronBee C
typedef struct ib_engine_t ib_engine_t;

namespace IronBee {

/**
 * Const Engine; equivalent to a const pointer to ib_engine_t.
 *
 * Provides operators ==, !=, <, >, <=, >= and evaluation as a boolean for
 * singularity via CommonSemantics.
 *
 * See Engine for discussion of the engine.
 *
 * @sa Engine
 * @sa ironbeepp
 * @sa ib_engine_t
 * @nosubgrouping
 **/
class ConstEngine :
    public CommonSemantics<ConstEngine>
{
public:
    /**
     * Construct singular ConstEngine.
     *
     * All behavior of a singular ConstEngine is undefined except for
     * assignment, copying, comparison, and evaluate-as-bool.
     **/
    ConstEngine();

    /**
     * @name C Interoperability
     * Methods to access underlying C types.
     **/
    ///@{

    //! const ib_engine_t accessor.
    // Intentionally inlined.
    const ib_engine_t* ib() const
    {
        return m_ib;
    }

    //! Construct Engine from ib_engine_t.
    explicit
    ConstEngine(const ib_engine_t* ib_engine);

    ///@}

private:
    const ib_engine_t* m_ib;
};

/**
 * Engine; equivalent to a pointer to ib_engine_t.
 *
 * An Engine can be treated as a ConstEngine.  See @ref ironbeepp for
 * details on IronBee++ object semantics.
 *
 * The IronBee Engine is the central component of IronBee that processes
 * inputs and calls hooks.  It is a complex state machine.  See
 * IronBeeEngineState.
 *
 * This class provides some of the C API functionality.  In particular, it
 * allows module writers to register hooks with the engine and provides
 * logging functionality.
 *
 * @sa ironbeepp
 * @sa IronBeeEngineState
 * @sa ib_engine_t
 * @sa ConstEngine
 * @nosubgrouping
 **/
class Engine :
    public ConstEngine
{
public:
    /**
     * Remove the constness of a ConstEngine.
     *
     * @warning This is as dangerous as a @c const_cast, use carefully.
     *
     * @param[in] bs ConstEngine to remove const from.
     * @returns Engine pointing to same underlying byte string as @a bs.
     **/
    static Engine remove_const(ConstEngine engine);

    /**
     * Construct singular Engine.
     *
     * All behavior of a singular Engine is undefined except for
     * assignment, copying, comparison, and evaluate-as-bool.
     **/
    Engine();

    /**
     * @name Hooks
     * Methods to register hooks.
     *
     * See IronBeeEngineState for details on the states and transitions.
     **/
    ///@{

    ///@}

    /**
     * @name C Interoperability
     * Methods to access underlying C types.
     **/
    ///@{

    //! const ib_engine_t accessor.
    // Intentionally inlined.
    ib_engine_t* ib() const
    {
        return m_ib;
    }

    //! Construct Engine from ib_engine_t.
    explicit
    Engine(ib_engine_t* ib_engine);

    ///@}

private:
    ib_engine_t* m_ib;
};

/**
 * Output operator for Engine.
 *
 * Outputs Engine[@e value] to @a o where @e value is replaced with
 * the value of the bytestring.
 *
 * @param[in] o           Ostream to output to.
 * @param[in] byte_string Engine to output.
 * @return @a o
 **/
std::ostream& operator<<(std::ostream& o, const ConstEngine& engine);

} // IronBee

#endif
<|endoftext|>


<commit_before>// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#include <set>

#include "onnxruntime_extensions.h"
#include "ocos.h"

class ExternalCustomOps {
 public:
  ExternalCustomOps() {
  }

  static ExternalCustomOps& instance() {
    static ExternalCustomOps g_instance;
    return g_instance;
  }

  void Add(const OrtCustomOp* c_op) {
    op_array_.push_back(c_op);
  }

  const OrtCustomOp* GetNextOp(size_t& idx) {
    if (idx >= op_array_.size()) {
      return nullptr;
    }

    return op_array_[idx++];
  }

  ExternalCustomOps(ExternalCustomOps const&) = delete;
  void operator=(ExternalCustomOps const&) = delete;

 private:
  std::vector<const OrtCustomOp*> op_array_;
};

extern "C" bool ORT_API_CALL AddExternalCustomOp(const OrtCustomOp* c_op) {
  ExternalCustomOps::instance().Add(c_op);
  return true;
}

extern "C" OrtStatus* ORT_API_CALL RegisterCustomOps(OrtSessionOptions* options, const OrtApiBase* api) {
  OrtCustomOpDomain* domain = nullptr;
  const OrtApi* ortApi = api->GetApi(ORT_API_VERSION);
  std::set<std::string> pyop_nameset;
  OrtStatus* status = nullptr;

#if defined(PYTHON_OP_SUPPORT)
  if (status = RegisterPythonDomainAndOps(options, ortApi)){
    return status;
  }
#endif // PYTHON_OP_SUPPORT

  if (status = ortApi->CreateCustomOpDomain(c_OpDomain, &domain)) {
    return status;
  }

#if defined(PYTHON_OP_SUPPORT)
  size_t count = 0;
  const OrtCustomOp* c_ops = FetchPyCustomOps(count);
  while (c_ops != nullptr) {
    if (status = ortApi->CustomOpDomain_Add(domain, c_ops)) {
      return status;
    } else {
      pyop_nameset.emplace(c_ops->GetName(c_ops));
    }
    ++count;
    c_ops = FetchPyCustomOps(count);
  }
#endif

  static std::vector<FxLoadCustomOpFactory> c_factories = {
    LoadCustomOpClasses<CustomOpClassBegin>
#if defined(ENABLE_TF_STRING)
    , LoadCustomOpClasses_Text
#endif // ENABLE_TF_STRING
#if defined(ENABLE_MATH)
    , LoadCustomOpClasses_Math
#endif
#if defined(ENABLE_TOKENIZER)
    , LoadCustomOpClasses_Tokenizer
#endif
  };

  for (auto fx : c_factories) {
    auto ops = fx();
    while (*ops != nullptr) {
      if (pyop_nameset.find((*ops)->GetName(*ops)) == pyop_nameset.end()) {
        if (status = ortApi->CustomOpDomain_Add(domain, *ops)) {
          return status;
        }
      }
      ++ops;
    }
  }

  size_t idx = 0;
  const OrtCustomOp* e_ops = ExternalCustomOps::instance().GetNextOp(idx);
  while (e_ops != nullptr) {
    if (pyop_nameset.find(e_ops->GetName(e_ops)) == pyop_nameset.end()) {
      if (status = ortApi->CustomOpDomain_Add(domain, e_ops)) {
        return status;
      }
      e_ops = ExternalCustomOps::instance().GetNextOp(idx);
    }
  }

  return ortApi->AddCustomOpDomain(options, domain);
}
<commit_msg>Ensure custom op domain is released (#234)<commit_after>// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#include <mutex>
#include <set>

#include "onnxruntime_extensions.h"
#include "ocos.h"

struct OrtCustomOpDomainDeleter {
  explicit OrtCustomOpDomainDeleter(const OrtApi* ort_api) {
    ort_api_ = ort_api;
  }
  void operator()(OrtCustomOpDomain* domain) const {
    ort_api_->ReleaseCustomOpDomain(domain);
  }

  const OrtApi* ort_api_;
};

using OrtCustomOpDomainUniquePtr = std::unique_ptr<OrtCustomOpDomain, OrtCustomOpDomainDeleter>;
static std::vector<OrtCustomOpDomainUniquePtr> ort_custom_op_domain_container;
static std::mutex ort_custom_op_domain_mutex;

static void AddOrtCustomOpDomainToContainer(OrtCustomOpDomain* domain, const OrtApi* ort_api) {
  std::lock_guard<std::mutex> lock(ort_custom_op_domain_mutex);
  auto ptr = std::unique_ptr<OrtCustomOpDomain, OrtCustomOpDomainDeleter>(domain, OrtCustomOpDomainDeleter(ort_api));
  ort_custom_op_domain_container.push_back(std::move(ptr));
}

class ExternalCustomOps {
 public:
  ExternalCustomOps() {
  }

  static ExternalCustomOps& instance() {
    static ExternalCustomOps g_instance;
    return g_instance;
  }

  void Add(const OrtCustomOp* c_op) {
    op_array_.push_back(c_op);
  }

  const OrtCustomOp* GetNextOp(size_t& idx) {
    if (idx >= op_array_.size()) {
      return nullptr;
    }

    return op_array_[idx++];
  }

  ExternalCustomOps(ExternalCustomOps const&) = delete;
  void operator=(ExternalCustomOps const&) = delete;

 private:
  std::vector<const OrtCustomOp*> op_array_;
};

extern "C" bool ORT_API_CALL AddExternalCustomOp(const OrtCustomOp* c_op) {
  ExternalCustomOps::instance().Add(c_op);
  return true;
}

extern "C" OrtStatus* ORT_API_CALL RegisterCustomOps(OrtSessionOptions* options, const OrtApiBase* api) {
  OrtCustomOpDomain* domain = nullptr;
  const OrtApi* ortApi = api->GetApi(ORT_API_VERSION);
  std::set<std::string> pyop_nameset;
  OrtStatus* status = nullptr;

#if defined(PYTHON_OP_SUPPORT)
  if (status = RegisterPythonDomainAndOps(options, ortApi)){
    return status;
  }
#endif // PYTHON_OP_SUPPORT

  if (status = ortApi->CreateCustomOpDomain(c_OpDomain, &domain)) {
    return status;
  }

  AddOrtCustomOpDomainToContainer(domain, ortApi);

#if defined(PYTHON_OP_SUPPORT)
  size_t count = 0;
  const OrtCustomOp* c_ops = FetchPyCustomOps(count);
  while (c_ops != nullptr) {
    if (status = ortApi->CustomOpDomain_Add(domain, c_ops)) {
      return status;
    } else {
      pyop_nameset.emplace(c_ops->GetName(c_ops));
    }
    ++count;
    c_ops = FetchPyCustomOps(count);
  }
#endif

  static std::vector<FxLoadCustomOpFactory> c_factories = {
    LoadCustomOpClasses<CustomOpClassBegin>
#if defined(ENABLE_TF_STRING)
    , LoadCustomOpClasses_Text
#endif // ENABLE_TF_STRING
#if defined(ENABLE_MATH)
    , LoadCustomOpClasses_Math
#endif
#if defined(ENABLE_TOKENIZER)
    , LoadCustomOpClasses_Tokenizer
#endif
  };

  for (auto fx : c_factories) {
    auto ops = fx();
    while (*ops != nullptr) {
      if (pyop_nameset.find((*ops)->GetName(*ops)) == pyop_nameset.end()) {
        if (status = ortApi->CustomOpDomain_Add(domain, *ops)) {
          return status;
        }
      }
      ++ops;
    }
  }

  size_t idx = 0;
  const OrtCustomOp* e_ops = ExternalCustomOps::instance().GetNextOp(idx);
  while (e_ops != nullptr) {
    if (pyop_nameset.find(e_ops->GetName(e_ops)) == pyop_nameset.end()) {
      if (status = ortApi->CustomOpDomain_Add(domain, e_ops)) {
        return status;
      }
      e_ops = ExternalCustomOps::instance().GetNextOp(idx);
    }
  }

  return ortApi->AddCustomOpDomain(options, domain);
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2009-2010, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

#ifndef LIBPORT_TYPE_INFO_HH
# define LIBPORT_TYPE_INFO_HH

namespace libport
{
  class TypeInfo
  {
  public:
    TypeInfo(const ::std::type_info& info);
    template <typename T>
    explicit TypeInfo(const T& obj);

    bool operator <(const TypeInfo& other) const;
    bool operator==(const TypeInfo& other) const;

    std::string name() const;

  private:
    const ::std::type_info* info_;
  };

  std::ostream& operator << (std::ostream& out, const TypeInfo& info);
}

# include <libport/type-info.hxx>

#endif
<commit_msg>Add missing include.<commit_after>/*
 * Copyright (C) 2009-2010, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

#ifndef LIBPORT_TYPE_INFO_HH
# define LIBPORT_TYPE_INFO_HH

# include <string>

namespace libport
{
  class TypeInfo
  {
  public:
    TypeInfo(const ::std::type_info& info);
    template <typename T>
    explicit TypeInfo(const T& obj);

    bool operator <(const TypeInfo& other) const;
    bool operator==(const TypeInfo& other) const;

    std::string name() const;

  private:
    const ::std::type_info* info_;
  };

  std::ostream& operator << (std::ostream& out, const TypeInfo& info);
}

# include <libport/type-info.hxx>

#endif
<|endoftext|>


<commit_before>/*
 * predixy - A high performance and full features proxy for redis.
 * Copyright (C) 2017 Joyield, Inc. <joyield.com@gmail.com>
 * All rights reserved.
 */

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/uio.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <fcntl.h>
#include <string.h>
#include <string>
#include "Socket.h"
#include "Util.h"
#include "Logger.h"
#include "Timer.h"

Socket::Socket(int fd):
    mClassType(RawType),
    mFd(fd),
    mEvts(0),
    mStatus(fd >= 0 ? Normal : None)
{
}

Socket::Socket(int domain, int type, int protocol):
    mClassType(RawType),
    mFd(Socket::socket(domain, type, protocol)),
    mStatus(Normal)
{
}

Socket::~Socket()
{
    close();
}

void Socket::close()
{
    if (mFd >= 0) {
        ::close(mFd);
        mFd = -1;
        mEvts = 0;
        mStatus = None;
    }
}

void Socket::attach(int fd)
{
    close();
    mFd = fd;
    mEvts = 0;
    mStatus = fd >= 0 ? Normal : None;
}

void Socket::detach()
{
    mFd = -1;
    mEvts = 0;
    mStatus = None;
}

const char* Socket::statusStr() const
{
    static const char* strs[] = {
        "Normal",
        "None",
        "End",
        "IOError",
        "EventError",
        "ExceptError"
    };
    return mStatus < CustomStatus ? strs[mStatus] : "Custom";
}

int Socket::socket(int domain, int type, int protocol)
{
    int fd = ::socket(domain, type, protocol);
    if (fd < 0) {
        Throw(SocketCallFail, "%s", StrError());
    }
    return fd;
}

void Socket::getFirstAddr(const char* addr, int type, int protocol, sockaddr* res, socklen_t* len)
{
    if (*addr == '/') { //unix socket
        struct sockaddr_un sun;
        memset(&sun, 0, sizeof(sun));
        sun.sun_family = AF_UNIX;
        strncpy(sun.sun_path, addr, sizeof(sun.sun_path));
        if (*len < sizeof(sun)) {
            *len = sizeof(sun);
            Throw(AddrLenTooShort, "result address space too short");
        }
        *len = sizeof(sun);
        memcpy(res, &sun, *len);
    } else {
        std::string tmp;
        const char* host = addr;
        const char* port = strchr(addr, ':');
        if (port) {
            tmp.append(addr, port - addr);
            host = tmp.c_str();
            port++;
        }
        struct addrinfo hints;
        struct addrinfo *dst;
        memset(&hints, 0, sizeof(hints));
        hints.ai_family = AF_UNSPEC;
        hints.ai_socktype = type;
        hints.ai_flags = AI_PASSIVE;
        hints.ai_protocol = protocol;
        int s = getaddrinfo(host, port, &hints, &dst);
        if (s != 0) {
            Throw(InvalidAddr, "invalid addr %s:%s", addr, gai_strerror(s));
        }
        if (!dst) {
            Throw(InvalidAddr, "invalid addr %s", addr);
        }
        if (*len < dst->ai_addrlen) {
            *len = dst->ai_addrlen;
            Throw(AddrLenTooShort, "result address space too short");
        }
        *len = dst->ai_addrlen;
        memcpy(res, dst->ai_addr, *len);
        freeaddrinfo(dst);
    }
}

bool Socket::setNonBlock(bool val)
{
    int flags = fcntl(mFd, F_GETFL, NULL);
    if (flags < 0) {
        return false;
    }
    if (val) {
        flags |= O_NONBLOCK;
    } else {
        flags &= ~O_NONBLOCK;
    }
    int ret = fcntl(mFd, F_SETFL, flags);
    return ret == 0;
}

bool Socket::setTcpNoDelay(bool val)
{
    int nodelay = val ? 1 : 0;
    socklen_t len = sizeof(nodelay);
    int ret = setsockopt(mFd, IPPROTO_TCP, TCP_NODELAY, &nodelay, len);
    return ret == 0;
}

bool Socket::setTcpKeepAlive(int interval)
{
    int val = 1;
    int ret = setsockopt(mFd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val));
    if (ret != 0) {
        return false;
    }
#ifdef __linux__
    val = interval;
    ret = setsockopt(mFd, IPPROTO_TCP, TCP_KEEPIDLE, &val, sizeof(val));
    if (ret != 0) {
        return false;
    }
    val = interval / 3;
    ret = setsockopt(mFd, IPPROTO_TCP, TCP_KEEPINTVL, &val, sizeof(val));
    if (ret != 0) {
        return false;
    }
    val = 3;
    ret = setsockopt(mFd, IPPROTO_TCP, TCP_KEEPCNT, &val, sizeof(val));
    if (ret != 0) {
        return false;
    }
#else
    ((void)interval); //Avoid unused var warning for non Linux systems
#endif
    return true;
}

int Socket::read(void* buf, int cnt)
{
    FuncCallTimer();
    while (cnt > 0) {
        int n = ::read(mFd, buf, cnt);
        if (n < 0) {
            if (errno == EAGAIN || errno == EWOULDBLOCK) {
                break;
            } else if (errno == EINTR) {
                continue;
            }
            mStatus = IOError;
        } else if (n == 0) {
            mStatus = End;
        }
        return n;
    }
    return 0;
}

int Socket::write(const void* buf, int cnt)
{
    FuncCallTimer();
    while (cnt > 0) {
        int n = ::write(mFd, buf, cnt);
        if (n < 0) {
            if (errno == EAGAIN || errno == EWOULDBLOCK) {
                break;
            } else if (errno == EINTR) {
                continue;
            }
            mStatus = IOError;
        }
        return n;
    }
    return 0;
}

int Socket::writev(const struct iovec* vecs, int cnt)
{
    FuncCallTimer();
    while (cnt > 0) {
        int n = ::writev(mFd, vecs, cnt);
        if (n < 0) {
            if (errno == EAGAIN || errno == EWOULDBLOCK) {
                return 0;
            } else if (errno == EINTR) {
                continue;
            }
            mStatus = IOError;
        }
        return n;
    }
    return 0;
}
<commit_msg>[fix] ipv6 address parsing<commit_after>/*
 * predixy - A high performance and full features proxy for redis.
 * Copyright (C) 2017 Joyield, Inc. <joyield.com@gmail.com>
 * All rights reserved.
 */

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/uio.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <fcntl.h>
#include <string.h>
#include <string>
#include "Socket.h"
#include "Util.h"
#include "Logger.h"
#include "Timer.h"

Socket::Socket(int fd):
    mClassType(RawType),
    mFd(fd),
    mEvts(0),
    mStatus(fd >= 0 ? Normal : None)
{
}

Socket::Socket(int domain, int type, int protocol):
    mClassType(RawType),
    mFd(Socket::socket(domain, type, protocol)),
    mStatus(Normal)
{
}

Socket::~Socket()
{
    close();
}

void Socket::close()
{
    if (mFd >= 0) {
        ::close(mFd);
        mFd = -1;
        mEvts = 0;
        mStatus = None;
    }
}

void Socket::attach(int fd)
{
    close();
    mFd = fd;
    mEvts = 0;
    mStatus = fd >= 0 ? Normal : None;
}

void Socket::detach()
{
    mFd = -1;
    mEvts = 0;
    mStatus = None;
}

const char* Socket::statusStr() const
{
    static const char* strs[] = {
        "Normal",
        "None",
        "End",
        "IOError",
        "EventError",
        "ExceptError"
    };
    return mStatus < CustomStatus ? strs[mStatus] : "Custom";
}

int Socket::socket(int domain, int type, int protocol)
{
    int fd = ::socket(domain, type, protocol);
    if (fd < 0) {
        Throw(SocketCallFail, "%s", StrError());
    }
    return fd;
}

void Socket::getFirstAddr(const char* addr, int type, int protocol, sockaddr* res, socklen_t* len)
{
    if (*addr == '/') { //unix socket
        struct sockaddr_un sun;
        memset(&sun, 0, sizeof(sun));
        sun.sun_family = AF_UNIX;
        strncpy(sun.sun_path, addr, sizeof(sun.sun_path));
        if (*len < sizeof(sun)) {
            *len = sizeof(sun);
            Throw(AddrLenTooShort, "result address space too short");
        }
        *len = sizeof(sun);
        memcpy(res, &sun, *len);
    } else {
        std::string tmp;
        const char* host = addr;
        const char* port = strrchr(addr, ':');
        if (port) {
            tmp.append(addr, port - addr);
            host = tmp.c_str();
            port++;
        }
        struct addrinfo hints;
        struct addrinfo *dst;
        memset(&hints, 0, sizeof(hints));
        hints.ai_family = AF_UNSPEC;
        hints.ai_socktype = type;
        hints.ai_flags = AI_PASSIVE;
        hints.ai_protocol = protocol;
        int s = getaddrinfo(host, port, &hints, &dst);
        if (s != 0) {
            Throw(InvalidAddr, "invalid addr %s:%s", addr, gai_strerror(s));
        }
        if (!dst) {
            Throw(InvalidAddr, "invalid addr %s", addr);
        }
        if (*len < dst->ai_addrlen) {
            *len = dst->ai_addrlen;
            Throw(AddrLenTooShort, "result address space too short");
        }
        *len = dst->ai_addrlen;
        memcpy(res, dst->ai_addr, *len);
        freeaddrinfo(dst);
    }
}

bool Socket::setNonBlock(bool val)
{
    int flags = fcntl(mFd, F_GETFL, NULL);
    if (flags < 0) {
        return false;
    }
    if (val) {
        flags |= O_NONBLOCK;
    } else {
        flags &= ~O_NONBLOCK;
    }
    int ret = fcntl(mFd, F_SETFL, flags);
    return ret == 0;
}

bool Socket::setTcpNoDelay(bool val)
{
    int nodelay = val ? 1 : 0;
    socklen_t len = sizeof(nodelay);
    int ret = setsockopt(mFd, IPPROTO_TCP, TCP_NODELAY, &nodelay, len);
    return ret == 0;
}

bool Socket::setTcpKeepAlive(int interval)
{
    int val = 1;
    int ret = setsockopt(mFd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val));
    if (ret != 0) {
        return false;
    }
#ifdef __linux__
    val = interval;
    ret = setsockopt(mFd, IPPROTO_TCP, TCP_KEEPIDLE, &val, sizeof(val));
    if (ret != 0) {
        return false;
    }
    val = interval / 3;
    ret = setsockopt(mFd, IPPROTO_TCP, TCP_KEEPINTVL, &val, sizeof(val));
    if (ret != 0) {
        return false;
    }
    val = 3;
    ret = setsockopt(mFd, IPPROTO_TCP, TCP_KEEPCNT, &val, sizeof(val));
    if (ret != 0) {
        return false;
    }
#else
    ((void)interval); //Avoid unused var warning for non Linux systems
#endif
    return true;
}

int Socket::read(void* buf, int cnt)
{
    FuncCallTimer();
    while (cnt > 0) {
        int n = ::read(mFd, buf, cnt);
        if (n < 0) {
            if (errno == EAGAIN || errno == EWOULDBLOCK) {
                break;
            } else if (errno == EINTR) {
                continue;
            }
            mStatus = IOError;
        } else if (n == 0) {
            mStatus = End;
        }
        return n;
    }
    return 0;
}

int Socket::write(const void* buf, int cnt)
{
    FuncCallTimer();
    while (cnt > 0) {
        int n = ::write(mFd, buf, cnt);
        if (n < 0) {
            if (errno == EAGAIN || errno == EWOULDBLOCK) {
                break;
            } else if (errno == EINTR) {
                continue;
            }
            mStatus = IOError;
        }
        return n;
    }
    return 0;
}

int Socket::writev(const struct iovec* vecs, int cnt)
{
    FuncCallTimer();
    while (cnt > 0) {
        int n = ::writev(mFd, vecs, cnt);
        if (n < 0) {
            if (errno == EAGAIN || errno == EWOULDBLOCK) {
                return 0;
            } else if (errno == EINTR) {
                continue;
            }
            mStatus = IOError;
        }
        return n;
    }
    return 0;
}
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2014 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_ATTRIBUTE_HPP
#define MAPNIK_ATTRIBUTE_HPP

// mapnik
#include <mapnik/value_types.hpp>
#include <mapnik/value.hpp>

// stl
#include <string>
#include <unordered_map>

namespace mapnik {

struct attribute
{
    std::string name_;
    explicit attribute(std::string const& name)
        : name_(name) {}

    template <typename V ,typename F>
    V const& value(F const& f) const
    {
        return f.get(name_);
    }

    std::string const& name() const { return name_;}
};

struct geometry_type_attribute
{
    template <typename V, typename F>
    V value(F const& f) const
    {
        mapnik::value_integer type = 0;
        //for (auto const& geom : f.paths())
        //{
        //    if (type != 0 && geom.type() != type)
        //    {
        //        return value_integer(4); // Collection
        //   }
        //    type = geom.type();
        //}
        // FIXME
        return type;
    }
};

struct global_attribute
{
    std::string name;
    explicit global_attribute(std::string const& name_)
        : name(name_) {}

    template <typename V, typename C>
    V const& operator() (C const& ctx)
    {
        return ctx.get(name);
    }
};

using attributes = std::unordered_map<std::string, value>;

}

#endif // MAPNIK_ATTRIBUTE_HPP
<commit_msg>return geometry_type(geom)<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2014 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_ATTRIBUTE_HPP
#define MAPNIK_ATTRIBUTE_HPP

// mapnik
#include <mapnik/value_types.hpp>
#include <mapnik/value.hpp>
#include <mapnik/geometry_type.hpp>
// stl
#include <string>
#include <unordered_map>

namespace mapnik {

struct attribute
{
    std::string name_;
    explicit attribute(std::string const& name)
        : name_(name) {}

    template <typename V ,typename F>
    V const& value(F const& f) const
    {
        return f.get(name_);
    }

    std::string const& name() const { return name_;}
};

struct geometry_type_attribute
{
    template <typename V, typename F>
    V value(F const& f) const
    {
        return new_geometry::geometry_type(f.get_geometry());
    }
};

struct global_attribute
{
    std::string name;
    explicit global_attribute(std::string const& name_)
        : name(name_) {}

    template <typename V, typename C>
    V const& operator() (C const& ctx)
    {
        return ctx.get(name);
    }
};

using attributes = std::unordered_map<std::string, value>;

}

#endif // MAPNIK_ATTRIBUTE_HPP
<|endoftext|>


<commit_before>/*
 * Koder is a code editor for Haiku based on Scintilla.
 *
 * Copyright (C) 2014-2015 Kacper Kasper <kacperkasper@gmail.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * 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; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include "Styler.h"

#include <cstdlib>
#include <libxml/parser.h>
#include <libxml/xpath.h>

#include <String.h>

#include "Editor.h"
#include "XmlDocument.h"
#include "XmlNode.h"

Styler::Styler(const char* path)
	:
	fDocument(new XmlDocument(path))
{
}

Styler::~Styler()
{
	delete fDocument;
}

void
Styler::ApplyGlobal(Editor* editor)
{
	uint32 count;
	XmlNode* defaultStyle = fDocument->GetNodesByXPath("/NotepadPlus/GlobalStyles/WidgetStyle[@styleID='32']", &count);

	int id, fg, bg, fs;
	_GetAttributesFromNode(defaultStyle[0], &id, &fg, &bg, &fs);

	font_family fixed;
	be_fixed_font->GetFamilyAndStyle(&fixed, NULL);
	editor->SendMessage(SCI_STYLESETFONT, id, (sptr_t) fixed);
	_SetAttributesInEditor(editor, id, fg, bg, fs);
	editor->SendMessage(SCI_STYLECLEARALL, 0, 0);

	delete []defaultStyle;

	XmlNode* globalStyle = fDocument->GetNodesByXPath("/NotepadPlus/GlobalStyles/WidgetStyle", &count);

	for(int i = 0; i < count; i++) {
		_GetAttributesFromNode(globalStyle[i], &id, &fg, &bg, &fs);

		if(id != 0 && id != 2069) {
			_SetAttributesInEditor(editor, id, fg, bg, fs);
		}
		else
		{
			BString name = globalStyle[i].GetAttribute("name");
			if(name == "Current line background colour") {
				editor->SendMessage(SCI_SETCARETLINEBACK, bg, 0);
				//editor->SendMessage(SCI_SETCARETLINEBACKALPHA, 128, 0);
			}
			else if(name == "White space symbol") {
				if(fg != -1) {
					editor->SendMessage(SCI_SETWHITESPACEFORE, true, fg);
				}
				if(bg != -1) {
					editor->SendMessage(SCI_SETWHITESPACEBACK, true, bg);
				}
			}
			else if(name == "Selected text colour") {
				if(fg != -1) {
					editor->SendMessage(SCI_SETSELFORE, true, fg);
				}
				if(bg != -1) {
					editor->SendMessage(SCI_SETSELBACK, true, bg);
				}
			}
			else if(name == "Caret colour") {
				editor->SendMessage(SCI_SETCARETFORE, fg, 0);
			}
			else if(name == "Edge colour") {
				editor->SendMessage(SCI_SETEDGECOLOUR, fg, 0);
			}
			else if(name == "Fold") {
				if(fg != -1) {
					editor->SendMessage(SCI_SETFOLDMARGINHICOLOUR, true, fg);
				}
				if(bg != -1) {
					editor->SendMessage(SCI_SETFOLDMARGINCOLOUR, true, bg);
				}
			}
		}
	}

	delete []globalStyle;
}

void
Styler::ApplyLanguage(Editor* editor, const char* lang)
{
	BString xpath("/NotepadPlus/LexerStyles/LexerType[@name='%s']/WordsStyle");
	xpath.ReplaceFirst("%s", lang);
	uint32 count;
	XmlNode* nodes = fDocument->GetNodesByXPath(xpath.String(), &count);
	int id, fg, bg, fs;
	for(int i = 0; i < count; i++) {
		_GetAttributesFromNode(nodes[i], &id, &fg, &bg, &fs);
		_SetAttributesInEditor(editor, id, fg, bg, fs);
	}

	delete []nodes;
}

void
Styler::_GetAttributesFromNode(XmlNode &node, int* styleId, int* fgColor, int* bgColor, int* fontStyle)
{
	*styleId = -1;
	*fgColor = -1;
	*bgColor = -1;
	*fontStyle = -1;

	BString temp;
	temp = node.GetAttribute("styleID");
	if(temp.IsEmpty() == false) {
		*styleId = strtol(temp.String(), NULL, 10);
	}
	temp = node.GetAttribute("fgColor");
	if(temp.IsEmpty() == false) {
		*fgColor = strtol(temp.String(), NULL, 16);
	}
	temp = node.GetAttribute("bgColor");
	if(temp.IsEmpty() == false) {
		*bgColor = strtol(temp.String(), NULL, 16);
	}
	temp = node.GetAttribute("fontStyle");
	if(temp.IsEmpty() == false) {
		*fontStyle = strtol(temp.String(), NULL, 10);
	}
}

void
Styler::_SetAttributesInEditor(Editor* editor, int styleId, int fgColor, int bgColor, int fontStyle)
{
	if(fgColor != -1) {
		editor->SendMessage(SCI_STYLESETFORE, styleId, fgColor);
	}
	if(bgColor != -1) {
		editor->SendMessage(SCI_STYLESETBACK, styleId, bgColor);
	}
	if(fontStyle != -1) {
		if(fontStyle & 1) {
			editor->SendMessage(SCI_STYLESETBOLD, styleId, true);
		}
		if(fontStyle & 2) {
			editor->SendMessage(SCI_STYLESETITALIC, styleId, true);
		}
		if(fontStyle & 4) {
			editor->SendMessage(SCI_STYLESETUNDERLINE, styleId, true);
		}
	}
}
<commit_msg>Get font size from system settings.<commit_after>/*
 * Koder is a code editor for Haiku based on Scintilla.
 *
 * Copyright (C) 2014-2015 Kacper Kasper <kacperkasper@gmail.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * 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; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include "Styler.h"

#include <cstdlib>
#include <libxml/parser.h>
#include <libxml/xpath.h>

#include <String.h>

#include "Editor.h"
#include "XmlDocument.h"
#include "XmlNode.h"

Styler::Styler(const char* path)
	:
	fDocument(new XmlDocument(path))
{
}

Styler::~Styler()
{
	delete fDocument;
}

void
Styler::ApplyGlobal(Editor* editor)
{
	uint32 count;
	XmlNode* defaultStyle = fDocument->GetNodesByXPath("/NotepadPlus/GlobalStyles/WidgetStyle[@styleID='32']", &count);

	int id, fg, bg, fs;
	_GetAttributesFromNode(defaultStyle[0], &id, &fg, &bg, &fs);

	font_family fixed;
	be_fixed_font->GetFamilyAndStyle(&fixed, NULL);
	editor->SendMessage(SCI_STYLESETFONT, id, (sptr_t) fixed);
	editor->SendMessage(SCI_STYLESETSIZE, id, (sptr_t) be_fixed_font->Size());
	_SetAttributesInEditor(editor, id, fg, bg, fs);
	editor->SendMessage(SCI_STYLECLEARALL, 0, 0);

	delete []defaultStyle;

	XmlNode* globalStyle = fDocument->GetNodesByXPath("/NotepadPlus/GlobalStyles/WidgetStyle", &count);

	for(int i = 0; i < count; i++) {
		_GetAttributesFromNode(globalStyle[i], &id, &fg, &bg, &fs);

		if(id != 0 && id != 2069) {
			_SetAttributesInEditor(editor, id, fg, bg, fs);
		}
		else
		{
			BString name = globalStyle[i].GetAttribute("name");
			if(name == "Current line background colour") {
				editor->SendMessage(SCI_SETCARETLINEBACK, bg, 0);
				//editor->SendMessage(SCI_SETCARETLINEBACKALPHA, 128, 0);
			}
			else if(name == "White space symbol") {
				if(fg != -1) {
					editor->SendMessage(SCI_SETWHITESPACEFORE, true, fg);
				}
				if(bg != -1) {
					editor->SendMessage(SCI_SETWHITESPACEBACK, true, bg);
				}
			}
			else if(name == "Selected text colour") {
				if(fg != -1) {
					editor->SendMessage(SCI_SETSELFORE, true, fg);
				}
				if(bg != -1) {
					editor->SendMessage(SCI_SETSELBACK, true, bg);
				}
			}
			else if(name == "Caret colour") {
				editor->SendMessage(SCI_SETCARETFORE, fg, 0);
			}
			else if(name == "Edge colour") {
				editor->SendMessage(SCI_SETEDGECOLOUR, fg, 0);
			}
			else if(name == "Fold") {
				if(fg != -1) {
					editor->SendMessage(SCI_SETFOLDMARGINHICOLOUR, true, fg);
				}
				if(bg != -1) {
					editor->SendMessage(SCI_SETFOLDMARGINCOLOUR, true, bg);
				}
			}
		}
	}

	delete []globalStyle;
}

void
Styler::ApplyLanguage(Editor* editor, const char* lang)
{
	BString xpath("/NotepadPlus/LexerStyles/LexerType[@name='%s']/WordsStyle");
	xpath.ReplaceFirst("%s", lang);
	uint32 count;
	XmlNode* nodes = fDocument->GetNodesByXPath(xpath.String(), &count);
	int id, fg, bg, fs;
	for(int i = 0; i < count; i++) {
		_GetAttributesFromNode(nodes[i], &id, &fg, &bg, &fs);
		_SetAttributesInEditor(editor, id, fg, bg, fs);
	}

	delete []nodes;
}

void
Styler::_GetAttributesFromNode(XmlNode &node, int* styleId, int* fgColor, int* bgColor, int* fontStyle)
{
	*styleId = -1;
	*fgColor = -1;
	*bgColor = -1;
	*fontStyle = -1;

	BString temp;
	temp = node.GetAttribute("styleID");
	if(temp.IsEmpty() == false) {
		*styleId = strtol(temp.String(), NULL, 10);
	}
	temp = node.GetAttribute("fgColor");
	if(temp.IsEmpty() == false) {
		*fgColor = strtol(temp.String(), NULL, 16);
	}
	temp = node.GetAttribute("bgColor");
	if(temp.IsEmpty() == false) {
		*bgColor = strtol(temp.String(), NULL, 16);
	}
	temp = node.GetAttribute("fontStyle");
	if(temp.IsEmpty() == false) {
		*fontStyle = strtol(temp.String(), NULL, 10);
	}
}

void
Styler::_SetAttributesInEditor(Editor* editor, int styleId, int fgColor, int bgColor, int fontStyle)
{
	if(fgColor != -1) {
		editor->SendMessage(SCI_STYLESETFORE, styleId, fgColor);
	}
	if(bgColor != -1) {
		editor->SendMessage(SCI_STYLESETBACK, styleId, bgColor);
	}
	if(fontStyle != -1) {
		if(fontStyle & 1) {
			editor->SendMessage(SCI_STYLESETBOLD, styleId, true);
		}
		if(fontStyle & 2) {
			editor->SendMessage(SCI_STYLESETITALIC, styleId, true);
		}
		if(fontStyle & 4) {
			editor->SendMessage(SCI_STYLESETUNDERLINE, styleId, true);
		}
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2021 The Orbit 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 "ObjectUtils/CoffFile.h"

#include <absl/strings/str_format.h>
#include <llvm/Demangle/Demangle.h>
#include <llvm/Object/Binary.h>
#include <llvm/Object/COFF.h>
#include <llvm/Object/ObjectFile.h>

#include "OrbitBase/Logging.h"
#include "OrbitBase/Result.h"
#include "symbol.pb.h"

namespace orbit_object_utils {

namespace {

using orbit_grpc_protos::ModuleSymbols;
using orbit_grpc_protos::SymbolInfo;

class CoffFileImpl : public CoffFile {
 public:
  CoffFileImpl(std::filesystem::path file_path,
               llvm::object::OwningBinary<llvm::object::ObjectFile>&& owning_binary);
  [[nodiscard]] ErrorMessageOr<orbit_grpc_protos::ModuleSymbols> LoadDebugSymbols() override;
  [[nodiscard]] bool HasDebugSymbols() const override;
  [[nodiscard]] std::string GetName() const override;
  [[nodiscard]] const std::filesystem::path& GetFilePath() const override;
  [[nodiscard]] bool IsElf() const override;
  [[nodiscard]] bool IsCoff() const override;

 private:
  ErrorMessageOr<uint64_t> GetSectionOffsetForSymbol(const llvm::object::SymbolRef& symbol_ref);
  ErrorMessageOr<SymbolInfo> CreateSymbolInfo(const llvm::object::SymbolRef& symbol_ref);
  const std::filesystem::path file_path_;
  llvm::object::OwningBinary<llvm::object::ObjectFile> owning_binary_;
  llvm::object::COFFObjectFile* object_file_;
  bool has_symbol_table_;
};

CoffFileImpl::CoffFileImpl(std::filesystem::path file_path,
                           llvm::object::OwningBinary<llvm::object::ObjectFile>&& owning_binary)
    : file_path_(std::move(file_path)),
      owning_binary_(std::move(owning_binary)),
      has_symbol_table_(false) {
  object_file_ = llvm::dyn_cast<llvm::object::COFFObjectFile>(owning_binary_.getBinary());
  // Per specification, a COFF file has a symbol table if the pointer to the symbol table is not 0.
  has_symbol_table_ = (object_file_->getSymbolTable() != 0);
}

ErrorMessageOr<uint64_t> CoffFileImpl::GetSectionOffsetForSymbol(
    const llvm::object::SymbolRef& symbol_ref) {
  // Symbol addresses are relative virtual addresses (RVAs) that are relative to the
  // start of the section. To get the address relative to the start of the object
  // file, we need to find the section and add the base address of the section.
  llvm::object::COFFSymbolRef coff_symbol_ref = object_file_->getCOFFSymbol(symbol_ref);
  int32_t section_id = coff_symbol_ref.getSectionNumber();
  const llvm::object::coff_section* section = nullptr;
  std::error_code err = object_file_->getSection(section_id, section);
  if (err) {
    return ErrorMessage(absl::StrFormat("Section of symbol not found: %s", err.message()));
  }
  return section->VirtualAddress;
}

ErrorMessageOr<SymbolInfo> CoffFileImpl::CreateSymbolInfo(
    const llvm::object::SymbolRef& symbol_ref) {
  if ((symbol_ref.getFlags() & llvm::object::BasicSymbolRef::SF_Undefined) != 0) {
    return ErrorMessage("Symbol is defined in another object file (SF_Undefined flag is set).");
  }
  const std::string name = symbol_ref.getName() ? symbol_ref.getName().get() : "";
  // Unknown type - skip and generate a warning.
  if (!symbol_ref.getType()) {
    LOG("WARNING: Type is not set for symbol \"%s\" in \"%s\", skipping.", name,
        file_path_.string());
    return ErrorMessage(absl::StrFormat(R"(Type is not set for symbol "%s" in "%s", skipping.)",
                                        name, file_path_.string()));
  }
  // Limit list of symbols to functions. Ignore sections and variables.
  if (symbol_ref.getType().get() != llvm::object::SymbolRef::ST_Function) {
    return ErrorMessage("Symbol is not a function.");
  }

  auto section_offset = GetSectionOffsetForSymbol(symbol_ref);
  if (section_offset.has_error()) {
    return ErrorMessage(absl::StrFormat("Error retrieving section offset for symbol \"%s\": %s",
                                        name, section_offset.error().message()));
  }
  SymbolInfo symbol_info;
  symbol_info.set_name(name);
  symbol_info.set_demangled_name(llvm::demangle(name));
  symbol_info.set_address(symbol_ref.getValue() + section_offset.value());
  symbol_info.set_size(symbol_ref.getCommonSize());
  return symbol_info;
}

ErrorMessageOr<ModuleSymbols> CoffFileImpl::LoadDebugSymbols() {
  if (!has_symbol_table_) {
    return ErrorMessage("COFF file does not have a symbol table.");
  }

  ModuleSymbols module_symbols;
  module_symbols.set_symbols_file_path(file_path_.string());

  for (const auto& symbol_ref : object_file_->symbols()) {
    auto symbol_or_error = CreateSymbolInfo(symbol_ref);
    if (symbol_or_error.has_value()) {
      *module_symbols.add_symbol_infos() = std::move(symbol_or_error.value());
    }
  }

  if (module_symbols.symbol_infos_size() == 0) {
    return ErrorMessage(
        "Unable to load symbols from object file, not even a single symbol of "
        "type function found.");
  }
  return module_symbols;
}

bool CoffFileImpl::HasDebugSymbols() const { return has_symbol_table_; }

const std::filesystem::path& CoffFileImpl::GetFilePath() const { return file_path_; }

std::string CoffFileImpl::GetName() const { return file_path_.filename().string(); }

bool CoffFileImpl::IsElf() const { return false; }
bool CoffFileImpl::IsCoff() const { return true; }

}  // namespace

ErrorMessageOr<std::unique_ptr<CoffFile>> CreateCoffFile(const std::filesystem::path& file_path) {
  // TODO(hebecker): Remove this explicit construction of StringRef when we
  // switch to LLVM10.
  const std::string file_path_str = file_path.string();
  const llvm::StringRef file_path_llvm{file_path_str};

  llvm::Expected<llvm::object::OwningBinary<llvm::object::ObjectFile>> object_file_or_error =
      llvm::object::ObjectFile::createObjectFile(file_path_llvm);

  if (!object_file_or_error) {
    return ErrorMessage(absl::StrFormat("Unable to load COFF file \"%s\": %s", file_path.string(),
                                        llvm::toString(object_file_or_error.takeError())));
  }

  llvm::object::OwningBinary<llvm::object::ObjectFile>& file = object_file_or_error.get();

  return CreateCoffFile(file_path, std::move(file));
}

ErrorMessageOr<std::unique_ptr<CoffFile>> CreateCoffFile(
    const std::filesystem::path& file_path,
    llvm::object::OwningBinary<llvm::object::ObjectFile>&& file) {
  llvm::object::ObjectFile* object_file = file.getBinary();
  if (llvm::dyn_cast<llvm::object::COFFObjectFile>(object_file) != nullptr) {
    return std::unique_ptr<CoffFile>(new CoffFileImpl(file_path, std::move(file)));
  } else {
    return ErrorMessage(absl::StrFormat("Unable to load object file \"%s\":", file_path.string()));
  }
}

}  // namespace orbit_object_utils
<commit_msg>Fix tripping assert in CoffFileImpl::LoadDebugSymbols<commit_after>// Copyright (c) 2021 The Orbit 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 "ObjectUtils/CoffFile.h"

#include <absl/strings/str_format.h>
#include <llvm/Demangle/Demangle.h>
#include <llvm/Object/Binary.h>
#include <llvm/Object/COFF.h>
#include <llvm/Object/ObjectFile.h>

#include "OrbitBase/Logging.h"
#include "OrbitBase/Result.h"
#include "symbol.pb.h"

namespace orbit_object_utils {

namespace {

using orbit_grpc_protos::ModuleSymbols;
using orbit_grpc_protos::SymbolInfo;

class CoffFileImpl : public CoffFile {
 public:
  CoffFileImpl(std::filesystem::path file_path,
               llvm::object::OwningBinary<llvm::object::ObjectFile>&& owning_binary);
  [[nodiscard]] ErrorMessageOr<orbit_grpc_protos::ModuleSymbols> LoadDebugSymbols() override;
  [[nodiscard]] bool HasDebugSymbols() const override;
  [[nodiscard]] std::string GetName() const override;
  [[nodiscard]] const std::filesystem::path& GetFilePath() const override;
  [[nodiscard]] bool IsElf() const override;
  [[nodiscard]] bool IsCoff() const override;

 private:
  ErrorMessageOr<uint64_t> GetSectionOffsetForSymbol(const llvm::object::SymbolRef& symbol_ref);
  ErrorMessageOr<SymbolInfo> CreateSymbolInfo(const llvm::object::SymbolRef& symbol_ref);
  const std::filesystem::path file_path_;
  llvm::object::OwningBinary<llvm::object::ObjectFile> owning_binary_;
  llvm::object::COFFObjectFile* object_file_;
  bool has_symbol_table_;
};

CoffFileImpl::CoffFileImpl(std::filesystem::path file_path,
                           llvm::object::OwningBinary<llvm::object::ObjectFile>&& owning_binary)
    : file_path_(std::move(file_path)),
      owning_binary_(std::move(owning_binary)),
      has_symbol_table_(false) {
  object_file_ = llvm::dyn_cast<llvm::object::COFFObjectFile>(owning_binary_.getBinary());
  // Per specification, a COFF file has a symbol table if the pointer to the symbol table is not 0.
  has_symbol_table_ = (object_file_->getSymbolTable() != 0);
}

ErrorMessageOr<uint64_t> CoffFileImpl::GetSectionOffsetForSymbol(
    const llvm::object::SymbolRef& symbol_ref) {
  // Symbol addresses are relative virtual addresses (RVAs) that are relative to the
  // start of the section. To get the address relative to the start of the object
  // file, we need to find the section and add the base address of the section.
  llvm::object::COFFSymbolRef coff_symbol_ref = object_file_->getCOFFSymbol(symbol_ref);
  int32_t section_id = coff_symbol_ref.getSectionNumber();
  const llvm::object::coff_section* section = nullptr;
  std::error_code err = object_file_->getSection(section_id, section);
  if (err) {
    return ErrorMessage(absl::StrFormat("Section of symbol not found: %s", err.message()));
  }
  return section->VirtualAddress;
}

ErrorMessageOr<SymbolInfo> CoffFileImpl::CreateSymbolInfo(
    const llvm::object::SymbolRef& symbol_ref) {
  if ((symbol_ref.getFlags() & llvm::object::BasicSymbolRef::SF_Undefined) != 0) {
    return ErrorMessage("Symbol is defined in another object file (SF_Undefined flag is set).");
  }
  const std::string name = symbol_ref.getName() ? symbol_ref.getName().get() : "";
  // Unknown type - skip and generate a warning.
  if (!symbol_ref.getType()) {
    LOG("WARNING: Type is not set for symbol \"%s\" in \"%s\", skipping.", name,
        file_path_.string());
    return ErrorMessage(absl::StrFormat(R"(Type is not set for symbol "%s" in "%s", skipping.)",
                                        name, file_path_.string()));
  }
  // Limit list of symbols to functions. Ignore sections and variables.
  if (symbol_ref.getType().get() != llvm::object::SymbolRef::ST_Function) {
    return ErrorMessage("Symbol is not a function.");
  }

  auto section_offset = GetSectionOffsetForSymbol(symbol_ref);
  if (section_offset.has_error()) {
    return ErrorMessage(absl::StrFormat("Error retrieving section offset for symbol \"%s\": %s",
                                        name, section_offset.error().message()));
  }
  SymbolInfo symbol_info;
  symbol_info.set_name(name);
  symbol_info.set_demangled_name(llvm::demangle(name));
  symbol_info.set_address(symbol_ref.getValue() + section_offset.value());

  llvm::object::COFFSymbolRef coff_symbol_ref = object_file_->getCOFFSymbol(symbol_ref);
  symbol_info.set_size(coff_symbol_ref.getValue());

  return symbol_info;
}

ErrorMessageOr<ModuleSymbols> CoffFileImpl::LoadDebugSymbols() {
  if (!has_symbol_table_) {
    return ErrorMessage("COFF file does not have a symbol table.");
  }

  ModuleSymbols module_symbols;
  module_symbols.set_symbols_file_path(file_path_.string());

  for (const auto& symbol_ref : object_file_->symbols()) {
    auto symbol_or_error = CreateSymbolInfo(symbol_ref);
    if (symbol_or_error.has_value()) {
      *module_symbols.add_symbol_infos() = std::move(symbol_or_error.value());
    }
  }

  if (module_symbols.symbol_infos_size() == 0) {
    return ErrorMessage(
        "Unable to load symbols from object file, not even a single symbol of "
        "type function found.");
  }
  return module_symbols;
}

bool CoffFileImpl::HasDebugSymbols() const { return has_symbol_table_; }

const std::filesystem::path& CoffFileImpl::GetFilePath() const { return file_path_; }

std::string CoffFileImpl::GetName() const { return file_path_.filename().string(); }

bool CoffFileImpl::IsElf() const { return false; }
bool CoffFileImpl::IsCoff() const { return true; }

}  // namespace

ErrorMessageOr<std::unique_ptr<CoffFile>> CreateCoffFile(const std::filesystem::path& file_path) {
  // TODO(hebecker): Remove this explicit construction of StringRef when we
  // switch to LLVM10.
  const std::string file_path_str = file_path.string();
  const llvm::StringRef file_path_llvm{file_path_str};

  llvm::Expected<llvm::object::OwningBinary<llvm::object::ObjectFile>> object_file_or_error =
      llvm::object::ObjectFile::createObjectFile(file_path_llvm);

  if (!object_file_or_error) {
    return ErrorMessage(absl::StrFormat("Unable to load COFF file \"%s\": %s", file_path.string(),
                                        llvm::toString(object_file_or_error.takeError())));
  }

  llvm::object::OwningBinary<llvm::object::ObjectFile>& file = object_file_or_error.get();

  return CreateCoffFile(file_path, std::move(file));
}

ErrorMessageOr<std::unique_ptr<CoffFile>> CreateCoffFile(
    const std::filesystem::path& file_path,
    llvm::object::OwningBinary<llvm::object::ObjectFile>&& file) {
  llvm::object::ObjectFile* object_file = file.getBinary();
  if (llvm::dyn_cast<llvm::object::COFFObjectFile>(object_file) != nullptr) {
    return std::unique_ptr<CoffFile>(new CoffFileImpl(file_path, std::move(file)));
  } else {
    return ErrorMessage(absl::StrFormat("Unable to load object file \"%s\":", file_path.string()));
  }
}

}  // namespace orbit_object_utils
<|endoftext|>


<commit_before>/*
 * This file is a part of the open source stm32plus library.
 * Copyright (c) 2011,2012,2013 Andy Brown <www.andybrown.me.uk>
 * Please see website for licensing terms.
 */

#include "config/stm32plus.h"
#include "config/flash/spi.h"
#include "config/sdcard.h"
#include "config/usart.h"
#include "config/filesystem.h"
#include "memory/scoped_ptr.h"
#include <vector>
#include <string>

using namespace stm32plus;

/**
 * This example programs a SPI flash device from files stored on an SD card and outputs
 * progress messages to a USART terminal. This programmer only requires the standard SPI
 * commands so it uses the 'StandardSpiFlashDevice' template. Other templates are available
 * that mixin commands specific to those devices.
 *
 * The SD card must contain an "index.txt" file in the "/spiflash" folder. "/spiflash/index.txt"
 * contains one line per file to flash The line is of the form:
 *
 *   <filename>=<start-address-in-flash-in-decimal>
 *
 * For example:
 *
 *   /spiflash/graphic1.bin=0
 *   /spiflash/graphic2.bin=16384
 *   /spiflash/assets/line.bin=24576
 *
 * Whitespace is not permitted anywhere on the text lines. It is important that each address
 * is a multiple of the device page size (usually 256 bytes). If it's not then you will get
 * data corruption. A chip-erase command is used to wipe the device before
 * programming.
 *
 * An example "spiflash" directory is included with this example that can be copied to
 * the root of your SD card. See the related 'flash_spi_reader' example for a demo that
 * reads back the example graphic files and displays them on an LCD.
 *
 * The default peripherals for this demo are SPI2, USART1, Winbond W25Q16DW 16Mbit flash. All
 * of these are customisable by you. The device identification code reported by the W25Q16DW
 * should be "ef6015".
 *
 * Compatible MCU:
 *   STM32F1
 *   STM32F4
 *
 * Tested on devices:
 *   STM32F103ZET6
 *   STM32F407VGT6
 */

class FlashSpiProgram {

  // these are the peripherals we will use

  typedef Spi2<> MySpi;
  typedef Usart1<> MyUsart;
  typedef spiflash::StandardSpiFlashDevice<MySpi> MyFlash;

  // declare the peripheral pointers

  MyUsart *_usart;
  MySpi *_spi;
  MyFlash *_flash;
  SdioDmaSdCard *_sdcard;
  FileSystem *_fs;
  UsartPollingOutputStream *_usartStream;

  // declare the program variables

  struct FlashEntry {
    char *filename;
    uint32_t length;
    uint32_t offset;
  };

  std::vector<FlashEntry> _flashEntries;

  public:

    void run() {

      // initialise the USART

      _usart=new MyUsart(57600);
      _usartStream=new UsartPollingOutputStream(*_usart);

      status("Initialising SD card.");

      // initialise the SD card

      _sdcard=new SdioDmaSdCard;

      if(errorProvider.hasError())
        error("SD card could not be initialised");

      // initialise the filesystem on the card

      NullTimeProvider timeProvider;

      if(!FileSystem::getInstance(*_sdcard,timeProvider,_fs))
        error("The file system on the SD card could not be initialised");

      // Initialise the SPI peripheral in master mode. The SPI speed is bus/4
      // Make sure that this is not too fast for your device.

      MySpi::Parameters spiParams;
      spiParams.spi_mode=SPI_Mode_Master;
      spiParams.spi_baudRatePrescaler=SPI_BaudRatePrescaler_4;
      spiParams.spi_cpol=SPI_CPOL_Low;
      spiParams.spi_cpha=SPI_CPHA_1Edge;

      _spi=new MySpi(spiParams);

      // initialise the flash device

      _flash=new MyFlash(*_spi);

      // show the device identifier

      showDeviceIdentifier();

      // read the index file

      readIndexFile();

      // erase the flash device

      eraseFlash();

      // write each file

      for(auto it=_flashEntries.begin();it!=_flashEntries.end();it++)
        writeFile(*it);

      // verify each file

      for(auto it=_flashEntries.begin();it!=_flashEntries.end();it++)
        verifyFile(*it);

      // done

      status("Success");
      for(;;);
    }

    /*
     * Show the flash device id
     */

    void showDeviceIdentifier() {

      uint8_t id[3];
      char output[7];

      if(!_flash->readJedecId(id,sizeof(id)))
        error("Unable to read the flash id code");

      StringUtil::toHex(id,sizeof(id),output);
      output[sizeof(output)-1]='\0';

      *_usartStream << "Flash id = " << output << "\r\n";
    }

    /*
     * Erase the entire device
     */

    void eraseFlash() {

      status("Erasing the entire flash device");

      if(!_flash->writeEnable())
        error("Unable to enable write access");

      if(!_flash->chipErase())
        error("Unable to execute the erase command");

      if(!_flash->waitForIdle())
        error("Failed to wait for the flash device to be idle");

      status("Erase completed");
    }

    /*
     * Write the file to the flash device
     */

    void writeFile(const FlashEntry& fe) {

      uint8_t page[MyFlash::PAGE_SIZE];
      scoped_ptr<File> file;
      uint32_t remaining,actuallyRead,address;

      *_usartStream << "Programming " << fe.filename << "\r\n";

      if(!_fs->openFile(fe.filename,file.address()))
        error("Failed to open file");

      address=fe.offset;

      for(remaining=fe.length;remaining;remaining-=actuallyRead) {

        // read a page from the file

        if(!file->read(page,sizeof(page),actuallyRead))
          error("Failed to read from file");

        // cannot hit EOF here

        if(!actuallyRead)
          error("Unexpected end of file");

        // wait for the device to go idle

        if(!_flash->waitForIdle())
          error("Failed to wait for the device to become idle");

        // enable writing

        if(!_flash->writeEnable())
          error("Unable to enable write access");

        if(!_flash->waitForIdle())
          error("Failed to wait for the device to become idle");

        // program the page

        if(!_flash->pageProgram(address,page,actuallyRead))
          error("Failed to program the page");

        // update for next

        address+=actuallyRead;
      }
    }

    /*
     * Verify the file just written to the device
     */

    void verifyFile(const FlashEntry& fe) {

      uint8_t filePage[MyFlash::PAGE_SIZE],flashPage[MyFlash::PAGE_SIZE];
      scoped_ptr<File> file;
      uint32_t remaining,actuallyRead,address;

      *_usartStream << "Verifying " << fe.filename << "\r\n";

      if(!_fs->openFile(fe.filename,file.address()))
        error("Failed to open file");

      address=fe.offset;

      for(remaining=fe.length;remaining;remaining-=actuallyRead) {

        // read a page from the file

        if(!file->read(filePage,sizeof(filePage),actuallyRead))
          error("Failed to read from file");

        // cannot hit EOF here

        if(!actuallyRead)
          error("Unexpected end of file");

        // read the page from the flash device

        if(!_flash->fastRead(address,flashPage,actuallyRead))
          error("Failed to read from the flash device");

        // compare it

        if(memcmp(filePage,flashPage,actuallyRead)!=0)
          error("Verify error: programming failed");

        // update for next

        address+=actuallyRead;
      }
    }

    /*
     * Read index.txt
     */

    void readIndexFile() {

      scoped_ptr<File> file;
      char line[200],*ptr;

      status("Reading index file.");

      // open the file

      if(!_fs->openFile("/spiflash/index.txt",file.address()))
        error("Cannot open /index.txt");

      // attach a reader and read each line

      FileReader reader(*file);

      while(reader.available()) {

        scoped_ptr<File> dataFile;

        // read line

        if(!reader.readLine(line,sizeof(line)))
          error("Failed to read line from file");

        // search for the = separator and break the text line at it

        if((ptr=strchr(line,'='))==nullptr)
          error("Badly formatted index.txt line - cannot find = symbol");

        *ptr='\0';

        // ensure this file can be opened

        if(!_fs->openFile(line,dataFile.address()))
          error("Cannot open data file");

        FlashEntry fe;
        fe.filename=strdup(line);
        fe.offset=atoi(ptr+1);
        fe.length=dataFile->getLength();

        _flashEntries.push_back(fe);

        *_usartStream << "Parsed " << fe.filename
                      << " offset " << StringUtil::Ascii(fe.offset)
                      << " length " << StringUtil::Ascii(fe.length)
                      << "\r\n";
      }

      *_usartStream << "Finished reading index, "
                    << StringUtil::Ascii(_flashEntries.size()) << ", entries read\r\n";
    }

    /*
     * Unrecoverable error
     */

    void error(const char *text) {
      status(text);
      for(;;);
    }

    /*
     * Write a status string to the usart
     */

    void status(const char *text) {
      *_usartStream << text << "\r\n";
    }
};

/*
 * Main entry point
 */

int main() {

  MillisecondTimer::initialise();

  FlashSpiProgram test;
  test.run();

  // not reached
  return 0;
}
<commit_msg>adding SPI pinout to comments in example<commit_after>/*
 * This file is a part of the open source stm32plus library.
 * Copyright (c) 2011,2012,2013 Andy Brown <www.andybrown.me.uk>
 * Please see website for licensing terms.
 */

#include "config/stm32plus.h"
#include "config/flash/spi.h"
#include "config/sdcard.h"
#include "config/usart.h"
#include "config/filesystem.h"
#include "memory/scoped_ptr.h"
#include <vector>
#include <string>

using namespace stm32plus;

/**
 * This example programs a SPI flash device from files stored on an SD card and outputs
 * progress messages to a USART terminal. This programmer only requires the standard SPI
 * commands so it uses the 'StandardSpiFlashDevice' template. Other templates are available
 * that mixin commands specific to those devices.
 *
 * The SD card must contain an "index.txt" file in the "/spiflash" folder. "/spiflash/index.txt"
 * contains one line per file to flash The line is of the form:
 *
 *   <filename>=<start-address-in-flash-in-decimal>
 *
 * For example:
 *
 *   /spiflash/graphic1.bin=0
 *   /spiflash/graphic2.bin=16384
 *   /spiflash/assets/line.bin=24576
 *
 * Whitespace is not permitted anywhere on the text lines. It is important that each address
 * is a multiple of the device page size (usually 256 bytes). If it's not then you will get
 * data corruption. A chip-erase command is used to wipe the device before
 * programming.
 *
 * An example "spiflash" directory is included with this example that can be copied to
 * the root of your SD card. See the related 'flash_spi_reader' example for a demo that
 * reads back the example graphic files and displays them on an LCD.
 *
 * The default peripherals for this demo are SPI2, USART1, Winbond W25Q16DW 16Mbit flash. All
 * of these are customisable by you. The device identification code reported by the W25Q16DW
 * should be "ef6015".
 *
 * The pinout for SPI2 is:
 *
 *   NSS  = PB12
 *   SCK  = PB13
 *   MISO = PB14
 *   MOSI = PB15
 *
 * Compatible MCU:
 *   STM32F1
 *   STM32F4
 *
 * Tested on devices:
 *   STM32F103ZET6
 *   STM32F407VGT6
 */

class FlashSpiProgram {

  // these are the peripherals we will use

  typedef Spi2<> MySpi;
  typedef Usart1<> MyUsart;
  typedef spiflash::StandardSpiFlashDevice<MySpi> MyFlash;

  // declare the peripheral pointers

  MyUsart *_usart;
  MySpi *_spi;
  MyFlash *_flash;
  SdioDmaSdCard *_sdcard;
  FileSystem *_fs;
  UsartPollingOutputStream *_usartStream;

  // declare the program variables

  struct FlashEntry {
    char *filename;
    uint32_t length;
    uint32_t offset;
  };

  std::vector<FlashEntry> _flashEntries;

  public:

    void run() {

      // initialise the USART

      _usart=new MyUsart(57600);
      _usartStream=new UsartPollingOutputStream(*_usart);

      status("Initialising SD card.");

      // initialise the SD card

      _sdcard=new SdioDmaSdCard;

      if(errorProvider.hasError())
        error("SD card could not be initialised");

      // initialise the filesystem on the card

      NullTimeProvider timeProvider;

      if(!FileSystem::getInstance(*_sdcard,timeProvider,_fs))
        error("The file system on the SD card could not be initialised");

      // Initialise the SPI peripheral in master mode. The SPI speed is bus/4
      // Make sure that this is not too fast for your device.

      MySpi::Parameters spiParams;
      spiParams.spi_mode=SPI_Mode_Master;
      spiParams.spi_baudRatePrescaler=SPI_BaudRatePrescaler_4;
      spiParams.spi_cpol=SPI_CPOL_Low;
      spiParams.spi_cpha=SPI_CPHA_1Edge;

      _spi=new MySpi(spiParams);

      // initialise the flash device

      _flash=new MyFlash(*_spi);

      // show the device identifier

      showDeviceIdentifier();

      // read the index file

      readIndexFile();

      // erase the flash device

      eraseFlash();

      // write each file

      for(auto it=_flashEntries.begin();it!=_flashEntries.end();it++)
        writeFile(*it);

      // verify each file

      for(auto it=_flashEntries.begin();it!=_flashEntries.end();it++)
        verifyFile(*it);

      // done

      status("Success");
      for(;;);
    }

    /*
     * Show the flash device id
     */

    void showDeviceIdentifier() {

      uint8_t id[3];
      char output[7];

      if(!_flash->readJedecId(id,sizeof(id)))
        error("Unable to read the flash id code");

      StringUtil::toHex(id,sizeof(id),output);
      output[sizeof(output)-1]='\0';

      *_usartStream << "Flash id = " << output << "\r\n";
    }

    /*
     * Erase the entire device
     */

    void eraseFlash() {

      status("Erasing the entire flash device");

      if(!_flash->writeEnable())
        error("Unable to enable write access");

      if(!_flash->chipErase())
        error("Unable to execute the erase command");

      if(!_flash->waitForIdle())
        error("Failed to wait for the flash device to be idle");

      status("Erase completed");
    }

    /*
     * Write the file to the flash device
     */

    void writeFile(const FlashEntry& fe) {

      uint8_t page[MyFlash::PAGE_SIZE];
      scoped_ptr<File> file;
      uint32_t remaining,actuallyRead,address;

      *_usartStream << "Programming " << fe.filename << "\r\n";

      if(!_fs->openFile(fe.filename,file.address()))
        error("Failed to open file");

      address=fe.offset;

      for(remaining=fe.length;remaining;remaining-=actuallyRead) {

        // read a page from the file

        if(!file->read(page,sizeof(page),actuallyRead))
          error("Failed to read from file");

        // cannot hit EOF here

        if(!actuallyRead)
          error("Unexpected end of file");

        // wait for the device to go idle

        if(!_flash->waitForIdle())
          error("Failed to wait for the device to become idle");

        // enable writing

        if(!_flash->writeEnable())
          error("Unable to enable write access");

        if(!_flash->waitForIdle())
          error("Failed to wait for the device to become idle");

        // program the page

        if(!_flash->pageProgram(address,page,actuallyRead))
          error("Failed to program the page");

        // update for next

        address+=actuallyRead;
      }
    }

    /*
     * Verify the file just written to the device
     */

    void verifyFile(const FlashEntry& fe) {

      uint8_t filePage[MyFlash::PAGE_SIZE],flashPage[MyFlash::PAGE_SIZE];
      scoped_ptr<File> file;
      uint32_t remaining,actuallyRead,address;

      *_usartStream << "Verifying " << fe.filename << "\r\n";

      if(!_fs->openFile(fe.filename,file.address()))
        error("Failed to open file");

      address=fe.offset;

      for(remaining=fe.length;remaining;remaining-=actuallyRead) {

        // read a page from the file

        if(!file->read(filePage,sizeof(filePage),actuallyRead))
          error("Failed to read from file");

        // cannot hit EOF here

        if(!actuallyRead)
          error("Unexpected end of file");

        // read the page from the flash device

        if(!_flash->fastRead(address,flashPage,actuallyRead))
          error("Failed to read from the flash device");

        // compare it

        if(memcmp(filePage,flashPage,actuallyRead)!=0)
          error("Verify error: programming failed");

        // update for next

        address+=actuallyRead;
      }
    }

    /*
     * Read index.txt
     */

    void readIndexFile() {

      scoped_ptr<File> file;
      char line[200],*ptr;

      status("Reading index file.");

      // open the file

      if(!_fs->openFile("/spiflash/index.txt",file.address()))
        error("Cannot open /index.txt");

      // attach a reader and read each line

      FileReader reader(*file);

      while(reader.available()) {

        scoped_ptr<File> dataFile;

        // read line

        if(!reader.readLine(line,sizeof(line)))
          error("Failed to read line from file");

        // search for the = separator and break the text line at it

        if((ptr=strchr(line,'='))==nullptr)
          error("Badly formatted index.txt line - cannot find = symbol");

        *ptr='\0';

        // ensure this file can be opened

        if(!_fs->openFile(line,dataFile.address()))
          error("Cannot open data file");

        FlashEntry fe;
        fe.filename=strdup(line);
        fe.offset=atoi(ptr+1);
        fe.length=dataFile->getLength();

        _flashEntries.push_back(fe);

        *_usartStream << "Parsed " << fe.filename
                      << " offset " << StringUtil::Ascii(fe.offset)
                      << " length " << StringUtil::Ascii(fe.length)
                      << "\r\n";
      }

      *_usartStream << "Finished reading index, "
                    << StringUtil::Ascii(_flashEntries.size()) << ", entries read\r\n";
    }

    /*
     * Unrecoverable error
     */

    void error(const char *text) {
      status(text);
      for(;;);
    }

    /*
     * Write a status string to the usart
     */

    void status(const char *text) {
      *_usartStream << text << "\r\n";
    }
};

/*
 * Main entry point
 */

int main() {

  MillisecondTimer::initialise();

  FlashSpiProgram test;
  test.run();

  // not reached
  return 0;
}
<|endoftext|>


<commit_before>//C++ source file - Open Producer - Copyright (C) 2002 Don Burns
//Distributed under the terms of the GNU LIBRARY GENERAL PUBLIC LICENSE (LGPL)
//as published by the Free Software Foundation.

// Simple example of use of Producer::RenderSurface
// The myGraphics class is a simple sample of how one would implement
// graphics drawing with Producer::RenderSurface

#include <osgUtil/UpdateVisitor>

#include <osgDB/ReadFile>

#include <osg/ShapeDrawable>
#include <osg/PositionAttitudeTransform>

#include <osgProducer/Viewer>

#include "DepthPartitionNode.h"

const double r_earth = 6378.137;
const double r_sun = 695990.0;
const double AU = 149697900.0;

osg::Node* createScene()
{
    // Create the Earth, in blue
    osg::ShapeDrawable *earth_sd = new osg::ShapeDrawable;
    osg::Sphere* earth_sphere = new osg::Sphere;
    earth_sphere->setRadius(r_earth);
    earth_sd->setShape(earth_sphere);
    earth_sd->setColor(osg::Vec4(0, 0, 1.0, 1.0));

    osg::Geode* earth = new osg::Geode;
    earth->setName("earth");
    earth->addDrawable(earth_sd);

    // Create the Sun, in yellow
    osg::ShapeDrawable *sun_sd = new osg::ShapeDrawable;
    osg::Sphere* sun_sphere = new osg::Sphere;
    sun_sphere->setRadius(r_sun);
    sun_sd->setShape(sun_sphere);
    sun_sd->setColor(osg::Vec4(1.0, 0.0, 0.0, 1.0));

    osg::Geode* sun = new osg::Geode;
    sun->setName("sun");
    sun->addDrawable(sun_sd);

    // Move the sun behind the earth
    osg::PositionAttitudeTransform *pat = new osg::PositionAttitudeTransform;
    pat->setPosition(osg::Vec3d(0.0, AU, 0.0));

    osg::Group* scene = new osg::Group;
    scene->addChild(earth);
    scene->addChild(pat);
    pat->addChild(sun);

    return scene;
}

int main( int argc, char **argv )
{

    // use an ArgumentParser object to manage the program arguments.
    osg::ArgumentParser arguments(&argc,argv);

    // set up the usage document, in case we need to print out how to use this program.
    arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the standard example of using osgProducer::CameraGroup.");
    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] ...");
    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");

    // construct the viewer.
    osgProducer::Viewer viewer(arguments);

    // set up the value with sensible default event handlers.
    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);

    // if user request help write it out to cout.
    if (arguments.read("-h") || arguments.read("--help"))
    {
        arguments.getApplicationUsage()->write(std::cout);
        return 1;
    }

    // any option left unread are converted into errors to write out later.
    arguments.reportRemainingOptionsAsUnrecognized();

    // report any errors if they have occured when parsing the program aguments.
    if (arguments.errors())
    {
        arguments.writeErrorMessages(std::cout);
        return 1;
    }

    bool needToSetHomePosition = false;

    // read the scene from the list of file specified commandline args.
    osg::ref_ptr<osg::Node> scene = osgDB::readNodeFiles(arguments);

    // if one hasn't been loaded create an earth and sun test model.
    if (!scene)
    {
        scene = createScene();
        needToSetHomePosition = true;
    }

    // Create a DepthPartitionNode to manage partitioning of the scene
    osg::ref_ptr<DepthPartitionNode> dpn = new DepthPartitionNode;
    dpn->addChild(scene.get());
    dpn->setActive(true); // Control whether the node analyzes the scene

    // pass the loaded scene graph to the viewer.
    viewer.setSceneData(dpn.get());

    if (needToSetHomePosition)
    {
        viewer.getKeySwitchMatrixManipulator()->setHomePosition(osg::Vec3d(0.0,-5.0*r_earth,0.0),osg::Vec3d(0.0,0.0,0.0),osg::Vec3d(0.0,0.0,1.0));
    }

    // create the windows and run the threads.
    viewer.realize();

    while( !viewer.done() )
    {
        // wait for all cull and draw threads to complete.
        viewer.sync();

        // update the scene by traversing it with the the update visitor which will
        // call all node update callbacks and animations.
        viewer.update();

        // fire off the cull and draw traversals of the scene.
        viewer.frame();

    }

    // wait for all cull and draw threads to complete before exit.
    viewer.sync();

    // run a clean up frame to delete all OpenGL objects.
    viewer.cleanup_frame();

    // wait for all the clean up frame to complete.
    viewer.sync();

    return 0;
}

<commit_msg>From Keith Steffen, changed instance of sun to sun_geode to avoid Solaris10 build issue with it defining "sun"?#!<commit_after>//C++ source file - Open Producer - Copyright (C) 2002 Don Burns
//Distributed under the terms of the GNU LIBRARY GENERAL PUBLIC LICENSE (LGPL)
//as published by the Free Software Foundation.

// Simple example of use of Producer::RenderSurface
// The myGraphics class is a simple sample of how one would implement
// graphics drawing with Producer::RenderSurface

#include <osgUtil/UpdateVisitor>

#include <osgDB/ReadFile>

#include <osg/ShapeDrawable>
#include <osg/PositionAttitudeTransform>

#include <osgProducer/Viewer>

#include "DepthPartitionNode.h"

const double r_earth = 6378.137;
const double r_sun = 695990.0;
const double AU = 149697900.0;

osg::Node* createScene()
{
    // Create the Earth, in blue
    osg::ShapeDrawable *earth_sd = new osg::ShapeDrawable;
    osg::Sphere* earth_sphere = new osg::Sphere;
    earth_sphere->setRadius(r_earth);
    earth_sd->setShape(earth_sphere);
    earth_sd->setColor(osg::Vec4(0, 0, 1.0, 1.0));

    osg::Geode* earth = new osg::Geode;
    earth->setName("earth");
    earth->addDrawable(earth_sd);

    // Create the Sun, in yellow
    osg::ShapeDrawable *sun_sd = new osg::ShapeDrawable;
    osg::Sphere* sun_sphere = new osg::Sphere;
    sun_sphere->setRadius(r_sun);
    sun_sd->setShape(sun_sphere);
    sun_sd->setColor(osg::Vec4(1.0, 0.0, 0.0, 1.0));

    osg::Geode* sun_geode = new osg::Geode;
    sun_geode->setName("sun");
    sun_geode->addDrawable(sun_sd);

    // Move the sun behind the earth
    osg::PositionAttitudeTransform *pat = new osg::PositionAttitudeTransform;
    pat->setPosition(osg::Vec3d(0.0, AU, 0.0));

    osg::Group* scene = new osg::Group;
    scene->addChild(earth);
    scene->addChild(pat);
    pat->addChild(sun_geode);

    return scene;
}

int main( int argc, char **argv )
{

    // use an ArgumentParser object to manage the program arguments.
    osg::ArgumentParser arguments(&argc,argv);

    // set up the usage document, in case we need to print out how to use this program.
    arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the standard example of using osgProducer::CameraGroup.");
    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] ...");
    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");

    // construct the viewer.
    osgProducer::Viewer viewer(arguments);

    // set up the value with sensible default event handlers.
    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);

    // if user request help write it out to cout.
    if (arguments.read("-h") || arguments.read("--help"))
    {
        arguments.getApplicationUsage()->write(std::cout);
        return 1;
    }

    // any option left unread are converted into errors to write out later.
    arguments.reportRemainingOptionsAsUnrecognized();

    // report any errors if they have occured when parsing the program aguments.
    if (arguments.errors())
    {
        arguments.writeErrorMessages(std::cout);
        return 1;
    }

    bool needToSetHomePosition = false;

    // read the scene from the list of file specified commandline args.
    osg::ref_ptr<osg::Node> scene = osgDB::readNodeFiles(arguments);

    // if one hasn't been loaded create an earth and sun test model.
    if (!scene)
    {
        scene = createScene();
        needToSetHomePosition = true;
    }

    // Create a DepthPartitionNode to manage partitioning of the scene
    osg::ref_ptr<DepthPartitionNode> dpn = new DepthPartitionNode;
    dpn->addChild(scene.get());
    dpn->setActive(true); // Control whether the node analyzes the scene

    // pass the loaded scene graph to the viewer.
    viewer.setSceneData(dpn.get());

    if (needToSetHomePosition)
    {
        viewer.getKeySwitchMatrixManipulator()->setHomePosition(osg::Vec3d(0.0,-5.0*r_earth,0.0),osg::Vec3d(0.0,0.0,0.0),osg::Vec3d(0.0,0.0,1.0));
    }

    // create the windows and run the threads.
    viewer.realize();

    while( !viewer.done() )
    {
        // wait for all cull and draw threads to complete.
        viewer.sync();

        // update the scene by traversing it with the the update visitor which will
        // call all node update callbacks and animations.
        viewer.update();

        // fire off the cull and draw traversals of the scene.
        viewer.frame();

    }

    // wait for all cull and draw threads to complete before exit.
    viewer.sync();

    // run a clean up frame to delete all OpenGL objects.
    viewer.cleanup_frame();

    // wait for all the clean up frame to complete.
    viewer.sync();

    return 0;
}

<|endoftext|>