<commit_before>//===--- Index.cpp -----------------------------------------------*- C++-*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "Index.h"
#include "Logger.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/SHA1.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;
namespace clang {
namespace clangd {

constexpr uint32_t SymbolLocation::Position::MaxLine;
constexpr uint32_t SymbolLocation::Position::MaxColumn;
void SymbolLocation::Position::setLine(uint32_t L) {
  if (L > MaxLine) {
    Line = MaxLine;
    return;
  }
  Line = L;
}
void SymbolLocation::Position::setColumn(uint32_t Col) {
  if (Col > MaxColumn) {
    Column = MaxColumn;
    return;
  }
  Column = Col;
}

raw_ostream &operator<<(raw_ostream &OS, const SymbolLocation &L) {
  if (!L)
    return OS << "(none)";
  return OS << L.FileURI << "[" << L.Start.line() << ":" << L.Start.column()
            << "-" << L.End.line() << ":" << L.End.column() << ")";
}

SymbolID::SymbolID(StringRef USR) {
  auto Hash = SHA1::hash(arrayRefFromStringRef(USR));
  static_assert(sizeof(Hash) >= RawSize, "RawSize larger than SHA1");
  memcpy(HashValue.data(), Hash.data(), RawSize);
}

raw_ostream &operator<<(raw_ostream &OS, const SymbolID &ID) {
  return OS << toHex(ID.raw());
}

SymbolID SymbolID::fromRaw(StringRef Raw) {
  SymbolID ID;
  assert(Raw.size() == RawSize);
  memcpy(ID.HashValue.data(), Raw.data(), RawSize);
  return ID;
}

std::string SymbolID::str() const { return toHex(raw()); }

Expected<SymbolID> SymbolID::fromStr(StringRef Str) {
  if (Str.size() != RawSize * 2)
    return createStringError(inconvertibleErrorCode(), "Bad ID length");
  for (char C : Str)
    if (!isHexDigit(C))
      return createStringError(inconvertibleErrorCode(), "Bad hex ID");
  return fromRaw(fromHex(Str));
}

raw_ostream &operator<<(raw_ostream &OS, SymbolOrigin O) {
  if (O == SymbolOrigin::Unknown)
    return OS << "unknown";
  constexpr static char Sigils[] = "ADSM4567";
  for (unsigned I = 0; I < sizeof(Sigils); ++I)
    if (static_cast<uint8_t>(O) & 1u << I)
      OS << Sigils[I];
  return OS;
}

raw_ostream &operator<<(raw_ostream &OS, Symbol::SymbolFlag F) {
  if (F == Symbol::None)
    return OS << "None";
  std::string s;
  if (F & Symbol::Deprecated)
    s += "deprecated|";
  if (F & Symbol::IndexedForCodeCompletion)
    s += "completion|";
  return OS << StringRef(s).rtrim('|');
}

raw_ostream &operator<<(raw_ostream &OS, const Symbol &S) {
  return OS << S.Scope << S.Name;
}

float quality(const Symbol &S) {
  // This avoids a sharp gradient for tail symbols, and also neatly avoids the
  // question of whether 0 references means a bad symbol or missing data.
  if (S.References < 3)
    return 1;
  return std::log(S.References);
}

SymbolSlab::const_iterator SymbolSlab::find(const SymbolID &ID) const {
  auto It = std::lower_bound(
      Symbols.begin(), Symbols.end(), ID,
      [](const Symbol &S, const SymbolID &I) { return S.ID < I; });
  if (It != Symbols.end() && It->ID == ID)
    return It;
  return Symbols.end();
}

// Copy the underlying data of the symbol into the owned arena.
static void own(Symbol &S, UniqueStringSaver &Strings) {
  visitStrings(S, [&](StringRef &V) { V = Strings.save(V); });
}

void SymbolSlab::Builder::insert(const Symbol &S) {
  auto R = SymbolIndex.try_emplace(S.ID, Symbols.size());
  if (R.second) {
    Symbols.push_back(S);
    own(Symbols.back(), UniqueStrings);
  } else {
    auto &Copy = Symbols[R.first->second] = S;
    own(Copy, UniqueStrings);
  }
}

SymbolSlab SymbolSlab::Builder::build() && {
  Symbols = {Symbols.begin(), Symbols.end()}; // Force shrink-to-fit.
  // Sort symbols so the slab can binary search over them.
  llvm::sort(Symbols,
             [](const Symbol &L, const Symbol &R) { return L.ID < R.ID; });
  // We may have unused strings from overwritten symbols. Build a new arena.
  BumpPtrAllocator NewArena;
  UniqueStringSaver Strings(NewArena);
  for (auto &S : Symbols)
    own(S, Strings);
  return SymbolSlab(std::move(NewArena), std::move(Symbols));
}

raw_ostream &operator<<(raw_ostream &OS, RefKind K) {
  if (K == RefKind::Unknown)
    return OS << "Unknown";
  static const std::vector<const char *> Messages = {"Decl", "Def", "Ref"};
  bool VisitedOnce = false;
  for (unsigned I = 0; I < Messages.size(); ++I) {
    if (static_cast<uint8_t>(K) & 1u << I) {
      if (VisitedOnce)
        OS << ", ";
      OS << Messages[I];
      VisitedOnce = true;
    }
  }
  return OS;
}

raw_ostream &operator<<(raw_ostream &OS, const Ref &R) {
  return OS << R.Location << ":" << R.Kind;
}

void RefSlab::Builder::insert(const SymbolID &ID, const Ref &S) {
  auto &M = Refs[ID];
  M.push_back(S);
  M.back().Location.FileURI = UniqueStrings.save(M.back().Location.FileURI);
}

RefSlab RefSlab::Builder::build() && {
  // We can reuse the arena, as it only has unique strings and we need them all.
  // Reallocate refs on the arena to reduce waste and indirections when reading.
  std::vector<std::pair<SymbolID, ArrayRef<Ref>>> Result;
  Result.reserve(Refs.size());
  size_t NumRefs = 0;
  for (auto &Sym : Refs) {
    auto &SymRefs = Sym.second;
    llvm::sort(SymRefs);
    // FIXME: do we really need to dedup?
    SymRefs.erase(std::unique(SymRefs.begin(), SymRefs.end()), SymRefs.end());

    NumRefs += SymRefs.size();
    auto *Array = Arena.Allocate<Ref>(SymRefs.size());
    std::uninitialized_copy(SymRefs.begin(), SymRefs.end(), Array);
    Result.emplace_back(Sym.first, ArrayRef<Ref>(Array, SymRefs.size()));
  }
  return RefSlab(std::move(Result), std::move(Arena), NumRefs);
}

void SwapIndex::reset(std::unique_ptr<SymbolIndex> Index) {
  // Keep the old index alive, so we don't destroy it under lock (may be slow).
  std::shared_ptr<SymbolIndex> Pin;
  {
    std::lock_guard<std::mutex> Lock(Mutex);
    Pin = std::move(this->Index);
    this->Index = std::move(Index);
  }
}
std::shared_ptr<SymbolIndex> SwapIndex::snapshot() const {
  std::lock_guard<std::mutex> Lock(Mutex);
  return Index;
}

bool fromJSON(const json::Value &Parameters, FuzzyFindRequest &Request) {
  json::ObjectMapper O(Parameters);
  int64_t Limit;
  bool OK =
      O && O.map("Query", Request.Query) && O.map("Scopes", Request.Scopes) &&
      O.map("Limit", Limit) &&
      O.map("RestrictForCodeCompletion", Request.RestrictForCodeCompletion) &&
      O.map("ProximityPaths", Request.ProximityPaths);
  if (OK && Limit <= std::numeric_limits<uint32_t>::max())
    Request.Limit = Limit;
  return OK;
}

json::Value toJSON(const FuzzyFindRequest &Request) {
  return json::Object{
      {"Query", Request.Query},
      {"Scopes", json::Array{Request.Scopes}},
      {"Limit", Request.Limit},
      {"RestrictForCodeCompletion", Request.RestrictForCodeCompletion},
      {"ProximityPaths", json::Array{Request.ProximityPaths}},
  };
}

bool SwapIndex::fuzzyFind(const FuzzyFindRequest &R,
                          function_ref<void(const Symbol &)> CB) const {
  return snapshot()->fuzzyFind(R, CB);
}
void SwapIndex::lookup(const LookupRequest &R,
                       function_ref<void(const Symbol &)> CB) const {
  return snapshot()->lookup(R, CB);
}
void SwapIndex::refs(const RefsRequest &R,
                     function_ref<void(const Ref &)> CB) const {
  return snapshot()->refs(R, CB);
}
size_t SwapIndex::estimateMemoryUsage() const {
  return snapshot()->estimateMemoryUsage();
}

} // namespace clangd
} // namespace clang
<commit_msg>[clangd] Remember to serialize AnyScope in FuzzyFindRequest json.<commit_after>//===--- Index.cpp -----------------------------------------------*- C++-*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "Index.h"
#include "Logger.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/SHA1.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;
namespace clang {
namespace clangd {

constexpr uint32_t SymbolLocation::Position::MaxLine;
constexpr uint32_t SymbolLocation::Position::MaxColumn;
void SymbolLocation::Position::setLine(uint32_t L) {
  if (L > MaxLine) {
    Line = MaxLine;
    return;
  }
  Line = L;
}
void SymbolLocation::Position::setColumn(uint32_t Col) {
  if (Col > MaxColumn) {
    Column = MaxColumn;
    return;
  }
  Column = Col;
}

raw_ostream &operator<<(raw_ostream &OS, const SymbolLocation &L) {
  if (!L)
    return OS << "(none)";
  return OS << L.FileURI << "[" << L.Start.line() << ":" << L.Start.column()
            << "-" << L.End.line() << ":" << L.End.column() << ")";
}

SymbolID::SymbolID(StringRef USR) {
  auto Hash = SHA1::hash(arrayRefFromStringRef(USR));
  static_assert(sizeof(Hash) >= RawSize, "RawSize larger than SHA1");
  memcpy(HashValue.data(), Hash.data(), RawSize);
}

raw_ostream &operator<<(raw_ostream &OS, const SymbolID &ID) {
  return OS << toHex(ID.raw());
}

SymbolID SymbolID::fromRaw(StringRef Raw) {
  SymbolID ID;
  assert(Raw.size() == RawSize);
  memcpy(ID.HashValue.data(), Raw.data(), RawSize);
  return ID;
}

std::string SymbolID::str() const { return toHex(raw()); }

Expected<SymbolID> SymbolID::fromStr(StringRef Str) {
  if (Str.size() != RawSize * 2)
    return createStringError(inconvertibleErrorCode(), "Bad ID length");
  for (char C : Str)
    if (!isHexDigit(C))
      return createStringError(inconvertibleErrorCode(), "Bad hex ID");
  return fromRaw(fromHex(Str));
}

raw_ostream &operator<<(raw_ostream &OS, SymbolOrigin O) {
  if (O == SymbolOrigin::Unknown)
    return OS << "unknown";
  constexpr static char Sigils[] = "ADSM4567";
  for (unsigned I = 0; I < sizeof(Sigils); ++I)
    if (static_cast<uint8_t>(O) & 1u << I)
      OS << Sigils[I];
  return OS;
}

raw_ostream &operator<<(raw_ostream &OS, Symbol::SymbolFlag F) {
  if (F == Symbol::None)
    return OS << "None";
  std::string s;
  if (F & Symbol::Deprecated)
    s += "deprecated|";
  if (F & Symbol::IndexedForCodeCompletion)
    s += "completion|";
  return OS << StringRef(s).rtrim('|');
}

raw_ostream &operator<<(raw_ostream &OS, const Symbol &S) {
  return OS << S.Scope << S.Name;
}

float quality(const Symbol &S) {
  // This avoids a sharp gradient for tail symbols, and also neatly avoids the
  // question of whether 0 references means a bad symbol or missing data.
  if (S.References < 3)
    return 1;
  return std::log(S.References);
}

SymbolSlab::const_iterator SymbolSlab::find(const SymbolID &ID) const {
  auto It = std::lower_bound(
      Symbols.begin(), Symbols.end(), ID,
      [](const Symbol &S, const SymbolID &I) { return S.ID < I; });
  if (It != Symbols.end() && It->ID == ID)
    return It;
  return Symbols.end();
}

// Copy the underlying data of the symbol into the owned arena.
static void own(Symbol &S, UniqueStringSaver &Strings) {
  visitStrings(S, [&](StringRef &V) { V = Strings.save(V); });
}

void SymbolSlab::Builder::insert(const Symbol &S) {
  auto R = SymbolIndex.try_emplace(S.ID, Symbols.size());
  if (R.second) {
    Symbols.push_back(S);
    own(Symbols.back(), UniqueStrings);
  } else {
    auto &Copy = Symbols[R.first->second] = S;
    own(Copy, UniqueStrings);
  }
}

SymbolSlab SymbolSlab::Builder::build() && {
  Symbols = {Symbols.begin(), Symbols.end()}; // Force shrink-to-fit.
  // Sort symbols so the slab can binary search over them.
  llvm::sort(Symbols,
             [](const Symbol &L, const Symbol &R) { return L.ID < R.ID; });
  // We may have unused strings from overwritten symbols. Build a new arena.
  BumpPtrAllocator NewArena;
  UniqueStringSaver Strings(NewArena);
  for (auto &S : Symbols)
    own(S, Strings);
  return SymbolSlab(std::move(NewArena), std::move(Symbols));
}

raw_ostream &operator<<(raw_ostream &OS, RefKind K) {
  if (K == RefKind::Unknown)
    return OS << "Unknown";
  static const std::vector<const char *> Messages = {"Decl", "Def", "Ref"};
  bool VisitedOnce = false;
  for (unsigned I = 0; I < Messages.size(); ++I) {
    if (static_cast<uint8_t>(K) & 1u << I) {
      if (VisitedOnce)
        OS << ", ";
      OS << Messages[I];
      VisitedOnce = true;
    }
  }
  return OS;
}

raw_ostream &operator<<(raw_ostream &OS, const Ref &R) {
  return OS << R.Location << ":" << R.Kind;
}

void RefSlab::Builder::insert(const SymbolID &ID, const Ref &S) {
  auto &M = Refs[ID];
  M.push_back(S);
  M.back().Location.FileURI = UniqueStrings.save(M.back().Location.FileURI);
}

RefSlab RefSlab::Builder::build() && {
  // We can reuse the arena, as it only has unique strings and we need them all.
  // Reallocate refs on the arena to reduce waste and indirections when reading.
  std::vector<std::pair<SymbolID, ArrayRef<Ref>>> Result;
  Result.reserve(Refs.size());
  size_t NumRefs = 0;
  for (auto &Sym : Refs) {
    auto &SymRefs = Sym.second;
    llvm::sort(SymRefs);
    // FIXME: do we really need to dedup?
    SymRefs.erase(std::unique(SymRefs.begin(), SymRefs.end()), SymRefs.end());

    NumRefs += SymRefs.size();
    auto *Array = Arena.Allocate<Ref>(SymRefs.size());
    std::uninitialized_copy(SymRefs.begin(), SymRefs.end(), Array);
    Result.emplace_back(Sym.first, ArrayRef<Ref>(Array, SymRefs.size()));
  }
  return RefSlab(std::move(Result), std::move(Arena), NumRefs);
}

void SwapIndex::reset(std::unique_ptr<SymbolIndex> Index) {
  // Keep the old index alive, so we don't destroy it under lock (may be slow).
  std::shared_ptr<SymbolIndex> Pin;
  {
    std::lock_guard<std::mutex> Lock(Mutex);
    Pin = std::move(this->Index);
    this->Index = std::move(Index);
  }
}
std::shared_ptr<SymbolIndex> SwapIndex::snapshot() const {
  std::lock_guard<std::mutex> Lock(Mutex);
  return Index;
}

bool fromJSON(const json::Value &Parameters, FuzzyFindRequest &Request) {
  json::ObjectMapper O(Parameters);
  int64_t Limit;
  bool OK =
      O && O.map("Query", Request.Query) && O.map("Scopes", Request.Scopes) &&
      O.map("AnyScope", Request.AnyScope) && O.map("Limit", Limit) &&
      O.map("RestrictForCodeCompletion", Request.RestrictForCodeCompletion) &&
      O.map("ProximityPaths", Request.ProximityPaths);
  if (OK && Limit <= std::numeric_limits<uint32_t>::max())
    Request.Limit = Limit;
  return OK;
}

json::Value toJSON(const FuzzyFindRequest &Request) {
  return json::Object{
      {"Query", Request.Query},
      {"Scopes", json::Array{Request.Scopes}},
      {"AnyScope", Request.AnyScope},
      {"Limit", Request.Limit},
      {"RestrictForCodeCompletion", Request.RestrictForCodeCompletion},
      {"ProximityPaths", json::Array{Request.ProximityPaths}},
  };
}

bool SwapIndex::fuzzyFind(const FuzzyFindRequest &R,
                          function_ref<void(const Symbol &)> CB) const {
  return snapshot()->fuzzyFind(R, CB);
}
void SwapIndex::lookup(const LookupRequest &R,
                       function_ref<void(const Symbol &)> CB) const {
  return snapshot()->lookup(R, CB);
}
void SwapIndex::refs(const RefsRequest &R,
                     function_ref<void(const Ref &)> CB) const {
  return snapshot()->refs(R, CB);
}
size_t SwapIndex::estimateMemoryUsage() const {
  return snapshot()->estimateMemoryUsage();
}

} // namespace clangd
} // namespace clang
<|endoftext|>


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

#pragma hdrstop

#ifndef _HINTIDS_HXX
#include "hintids.hxx"
#endif

#ifndef _COM_SUN_STAR_TEXT_XTEXTDOCUMENT_HPP_
#include <com/sun/star/text/XTextDocument.hpp>
#endif
#ifndef _XMLOFF_XMLFONTAUTOSTYLEPOOL_HXX
#include <xmloff/XMLFontAutoStylePool.hxx>
#endif
#ifndef _SVX_FONTITEM_HXX
#include <svx/fontitem.hxx>
#endif
#ifndef _UNOOBJ_HXX
#include <unoobj.hxx>
#endif
#ifndef _DOC_HXX //autogen wg. SwDoc
#include <doc.hxx>
#endif

#ifndef _XMLEXP_HXX
#include <xmlexp.hxx>
#endif

using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::text;

class SwXMLFontAutoStylePool_Impl: public XMLFontAutoStylePool
{
    public:

    SwXMLFontAutoStylePool_Impl( SwXMLExport& rExport );

};

SwXMLFontAutoStylePool_Impl::SwXMLFontAutoStylePool_Impl(
    SwXMLExport& rExport ) :
    XMLFontAutoStylePool( rExport )
{
    sal_uInt16 aWhichIds[3] = { RES_CHRATR_FONT, RES_CHRATR_CJK_FONT,
                                RES_CHRATR_CTL_FONT };

    Reference < XTextDocument > xTextDoc( rExport.GetModel(), UNO_QUERY );
    Reference < XText > xText = xTextDoc->getText();
    Reference<XUnoTunnel> xTextTunnel( xText, UNO_QUERY);
    ASSERT( xTextTunnel.is(), "missing XUnoTunnel for Cursor" );
    if( !xTextTunnel.is() )
        return;

    SwXText *pText = (SwXText *)xTextTunnel->getSomething(
                                        SwXText::getUnoTunnelId() );
    ASSERT( pText, "SwXText missing" );
    if( !pText )
        return;

    const SfxItemPool& rPool = pText->GetDoc()->GetAttrPool();
    const SfxPoolItem* pItem;
    for( sal_uInt16 i=0; i<3; i++ )
    {
        sal_uInt16 nWhichId = aWhichIds[i];

        const SvxFontItem& rFont =
            (const SvxFontItem&)rPool.GetDefaultItem( nWhichId );
        Add( rFont.GetFamilyName(), rFont.GetStyleName(),
             rFont.GetFamily(), rFont.GetPitch(), rFont.GetCharSet() );
        sal_uInt16 nItems = rPool.GetItemCount( nWhichId );
        for( sal_uInt16 j = 0; j < nItems; ++j )
        {
            if( 0 != (pItem = rPool.GetItem( nWhichId, j ) ) )
            {
                const SvxFontItem *pFont =
                            (const SvxFontItem *)pItem;
                Add( pFont->GetFamilyName(), pFont->GetStyleName(),
                     pFont->GetFamily(), pFont->GetPitch(),
                     pFont->GetCharSet() );
            }
        }
    }
}

XMLFontAutoStylePool* SwXMLExport::CreateFontAutoStylePool()
{
    return new SwXMLFontAutoStylePool_Impl( *this );
}
<commit_msg>INTEGRATION: CWS pchfix02 (1.6.2); FILE MERGED 2006/09/01 17:52:46 kaib 1.6.2.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: xmlfonte.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-16 22:29:06 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"

#ifndef _HINTIDS_HXX
#include "hintids.hxx"
#endif

#ifndef _COM_SUN_STAR_TEXT_XTEXTDOCUMENT_HPP_
#include <com/sun/star/text/XTextDocument.hpp>
#endif
#ifndef _XMLOFF_XMLFONTAUTOSTYLEPOOL_HXX
#include <xmloff/XMLFontAutoStylePool.hxx>
#endif
#ifndef _SVX_FONTITEM_HXX
#include <svx/fontitem.hxx>
#endif
#ifndef _UNOOBJ_HXX
#include <unoobj.hxx>
#endif
#ifndef _DOC_HXX //autogen wg. SwDoc
#include <doc.hxx>
#endif

#ifndef _XMLEXP_HXX
#include <xmlexp.hxx>
#endif

using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::text;

class SwXMLFontAutoStylePool_Impl: public XMLFontAutoStylePool
{
    public:

    SwXMLFontAutoStylePool_Impl( SwXMLExport& rExport );

};

SwXMLFontAutoStylePool_Impl::SwXMLFontAutoStylePool_Impl(
    SwXMLExport& rExport ) :
    XMLFontAutoStylePool( rExport )
{
    sal_uInt16 aWhichIds[3] = { RES_CHRATR_FONT, RES_CHRATR_CJK_FONT,
                                RES_CHRATR_CTL_FONT };

    Reference < XTextDocument > xTextDoc( rExport.GetModel(), UNO_QUERY );
    Reference < XText > xText = xTextDoc->getText();
    Reference<XUnoTunnel> xTextTunnel( xText, UNO_QUERY);
    ASSERT( xTextTunnel.is(), "missing XUnoTunnel for Cursor" );
    if( !xTextTunnel.is() )
        return;

    SwXText *pText = (SwXText *)xTextTunnel->getSomething(
                                        SwXText::getUnoTunnelId() );
    ASSERT( pText, "SwXText missing" );
    if( !pText )
        return;

    const SfxItemPool& rPool = pText->GetDoc()->GetAttrPool();
    const SfxPoolItem* pItem;
    for( sal_uInt16 i=0; i<3; i++ )
    {
        sal_uInt16 nWhichId = aWhichIds[i];

        const SvxFontItem& rFont =
            (const SvxFontItem&)rPool.GetDefaultItem( nWhichId );
        Add( rFont.GetFamilyName(), rFont.GetStyleName(),
             rFont.GetFamily(), rFont.GetPitch(), rFont.GetCharSet() );
        sal_uInt16 nItems = rPool.GetItemCount( nWhichId );
        for( sal_uInt16 j = 0; j < nItems; ++j )
        {
            if( 0 != (pItem = rPool.GetItem( nWhichId, j ) ) )
            {
                const SvxFontItem *pFont =
                            (const SvxFontItem *)pItem;
                Add( pFont->GetFamilyName(), pFont->GetStyleName(),
                     pFont->GetFamily(), pFont->GetPitch(),
                     pFont->GetCharSet() );
            }
        }
    }
}

XMLFontAutoStylePool* SwXMLExport::CreateFontAutoStylePool()
{
    return new SwXMLFontAutoStylePool_Impl( *this );
}
<|endoftext|>


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

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"

#include "swabstdlg.hxx"
#include "swuilib.hxx"

#include <osl/module.hxx>
#include <tools/string.hxx>

typedef SwAbstractDialogFactory* (__LOADONCALLAPI *SwFuncPtrCreateDialogFactory)();

extern "C" { static void SAL_CALL thisModule() {} }

SwAbstractDialogFactory* SwAbstractDialogFactory::Create()
{
    SwFuncPtrCreateDialogFactory fp = 0;
    static ::osl::Module aDialogLibrary;
    if ( aDialogLibrary.is() || aDialogLibrary.loadRelative( &thisModule, String( RTL_CONSTASCII_USTRINGPARAM( DLL_NAME ) ) ) )
        fp = ( SwAbstractDialogFactory* (__LOADONCALLAPI*)() )
            aDialogLibrary.getFunctionSymbol( ::rtl::OUString::createFromAscii("CreateDialogFactory") );
    if ( fp )
        return fp();
    return 0;
}
<commit_msg>INTEGRATION: CWS changefileheader (1.6.226); FILE MERGED 2008/03/31 16:57:41 rt 1.6.226.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: swabstdlg.cxx,v $
 * $Revision: 1.7 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"

#include "swabstdlg.hxx"
#include "swuilib.hxx"

#include <osl/module.hxx>
#include <tools/string.hxx>

typedef SwAbstractDialogFactory* (__LOADONCALLAPI *SwFuncPtrCreateDialogFactory)();

extern "C" { static void SAL_CALL thisModule() {} }

SwAbstractDialogFactory* SwAbstractDialogFactory::Create()
{
    SwFuncPtrCreateDialogFactory fp = 0;
    static ::osl::Module aDialogLibrary;
    if ( aDialogLibrary.is() || aDialogLibrary.loadRelative( &thisModule, String( RTL_CONSTASCII_USTRINGPARAM( DLL_NAME ) ) ) )
        fp = ( SwAbstractDialogFactory* (__LOADONCALLAPI*)() )
            aDialogLibrary.getFunctionSymbol( ::rtl::OUString::createFromAscii("CreateDialogFactory") );
    if ( fp )
        return fp();
    return 0;
}
<|endoftext|>


<commit_before>#ifndef _TASKING_SCHEDULER_HPP_
#define _TASKING_SCHEDULER_HPP_

#include "Scheduler.hpp"
#include <Timestamp.hpp>
#include <glog/logging.h>

DECLARE_int64( periodic_poll_ticks );

class TaskManager;
struct task_worker_args;

class TaskingScheduler : public Scheduler {
    private:
        ThreadQueue readyQ;
        ThreadQueue periodicQ;
        ThreadQueue unassignedQ;

        Thread * master;
        Thread * current_thread;
        threadid_t nextId;

        uint64_t num_idle;
        TaskManager * task_manager;
        uint64_t num_workers;

        Thread * getWorker ();

        task_worker_args * work_args;

        // STUB: replace with real periodic threads
        SoftXMT_Timestamp previous_periodic_ts;
        int periodctr;
        Thread * periodicDequeue() {
            // tick the timestap counter
            SoftXMT_tick();
            SoftXMT_Timestamp current_ts = SoftXMT_get_timestamp();

            if( current_ts - previous_periodic_ts > FLAGS_periodic_poll_ticks ) {
                previous_periodic_ts =  current_ts;
                return periodicQ.dequeue();
            } else {
                return NULL;
            }
        }
        //////

        bool queuesFinished();

        Thread * nextCoroutine ( bool isBlocking=true ) {
            do {
                Thread * result;

                // check for periodic tasks
                result = periodicDequeue();
                if (result != NULL) {
                 //   DVLOG(5) << current_thread->id << " scheduler: pick periodic";
                    return result;
                }

                // check ready tasks
                result = readyQ.dequeue();
                if (result != NULL) {
                //    DVLOG(5) << current_thread->id << " scheduler: pick ready";
                    return result;
                }

                // check for new workers
                result = getWorker();
                if (result != NULL) {
                  //  DVLOG(5) << current_thread->id << " scheduler: pick task worker";
                    return result;
                }

                // no coroutines can run, so handle
                /*DVLOG(5) << current_thread->id << " scheduler: no coroutines can run"
                    << "[isBlocking=" << isBlocking
                    << " periodQ=" << (periodicQ.empty() ? "empty" : "full")
                    << " unassignedQ=" << (unassignedQ.empty() ? "empty" : "full") << "]";*/
                usleep(1);
            } while ( isBlocking || !queuesFinished() );
            // exit if all threads exited, including idle workers
            // TODO just as use mightBeWork as shortcut, also kill all idle unassigned workers on cbarrier_exit

            return NULL;
        }

    public:
       TaskingScheduler ( Thread * master, TaskManager * taskman );

       Thread * get_current_thread() {
           return current_thread;
       }

       void assignTid( Thread * thr ) {
           thr->id = nextId++;
       }

      void createWorkers( uint64_t num );
      Thread* maybeSpawnCoroutines( );
      void onWorkerStart( );

       void unassigned( Thread * thr ) {
           unassignedQ.enqueue( thr );
       }

       void ready( Thread * thr ) {
            readyQ.enqueue( thr );
       }

       void periodic( Thread * thr ) {
           periodicQ.enqueue( thr );
       }

       /// run threads until all exit
       void run ( );

       bool thread_yield( );
       bool thread_yield_periodic( );
       void thread_suspend( );
       void thread_wake( Thread * next );
       void thread_yield_wake( Thread * next );
       void thread_suspend_wake( Thread * next );
       bool thread_idle( uint64_t total_idle );
       bool thread_idle( );
       void thread_join( Thread* wait_on );

       // Start running threads from <scheduler> until one dies.  Return that Thread
       // (which can't be restarted--it's trash.)  If <result> non-NULL,
       // store the Thread's exit value there.
       // If no threads to run, returns NULL.
       Thread * thread_wait( void **result );

       void thread_on_exit( );
};

struct task_worker_args {
    TaskManager *const tasks;
    TaskingScheduler *const scheduler;

    task_worker_args( TaskManager * task_manager, TaskingScheduler * sched )
        : tasks( task_manager )
        , scheduler( sched ) { }
};

/// Yield the CPU to the next Thread on your scheduler.  Doesn't ever touch
/// the master Thread.
inline bool TaskingScheduler::thread_yield( ) {
    CHECK( current_thread != master ) << "can't yield on a system Thread";

    ready( current_thread );

    Thread * yieldedThr = current_thread;

    Thread * next = nextCoroutine( );
    bool gotRescheduled = (next == yieldedThr);

    current_thread = next;
    //DVLOG(5) << "Thread " << yieldedThr->id << " yielding to " << next->id << (gotRescheduled ? " (same thread)." : " (diff thread).");
    thread_context_switch( yieldedThr, next, NULL);

    return gotRescheduled; // 0=another ran; 1=me got rescheduled immediately
}

/// For periodic threads: yield the CPU to the next Thread on your scheduler.  Doesn't ever touch
/// the master Thread.
inline bool TaskingScheduler::thread_yield_periodic( ) {
    CHECK( current_thread != master ) << "can't yield on a system Thread";

    periodic( current_thread );

    Thread * yieldedThr = current_thread;

    Thread * next = nextCoroutine( );
    bool gotRescheduled = (next == yieldedThr);

    current_thread = next;
    //DVLOG(5) << "Thread " << yieldedThr->id << " yielding to " << next->id << (gotRescheduled ? " (same thread)." : " (diff thread).");
    thread_context_switch( yieldedThr, next, NULL);

    return gotRescheduled; // 0=another ran; 1=me got rescheduled immediately
}

/// Suspend the current Thread. Thread is not placed on any queue.
inline void TaskingScheduler::thread_suspend( ) {
    CHECK( current_thread != master ) << "can't yield on a system Thread";
    CHECK( thread_is_running(current_thread) ) << "may only suspend a running coroutine";

    Thread * yieldedThr = current_thread;

    Thread * next = nextCoroutine( );

    current_thread = next;
    thread_context_switch( yieldedThr, next, NULL);
}

/// Wake a suspended Thread by putting it on the run queue.
/// For now, waking a running Thread is a fatal error.
/// For now, waking a queued Thread is also a fatal error.
/// For now, can only wake a Thread on your scheduler
inline void TaskingScheduler::thread_wake( Thread * next ) {
  CHECK( next->sched == this ) << "can only wake a Thread on your scheduler";
  CHECK( next->next == NULL ) << "woken Thread should not be on any queue";
  CHECK( !thread_is_running( next ) ) << "woken Thread should not be running";

  DVLOG(5) << "Thread " << current_thread->id << " wakes thread " << next->id;

  ready( next );
}

/// Yield the current Thread and wake a suspended thread.
/// For now, waking a running Thread is a fatal error.
/// For now, waking a queued Thread is also a fatal error.
inline void TaskingScheduler::thread_yield_wake( Thread * next ) {
    CHECK( current_thread != master ) << "can't yield on a system Thread";
    CHECK( next->sched == this ) << "can only wake a Thread on your scheduler";
    CHECK( next->next == NULL ) << "woken Thread should not be on any queue";
    CHECK( !thread_is_running( next ) ) << "woken Thread should not be running";

    Thread * yieldedThr = current_thread;
    ready( yieldedThr );

    current_thread = next;
    thread_context_switch( yieldedThr, next, NULL);
}

/// Suspend current Thread and wake a suspended thread.
/// For now, waking a running Thread is a fatal error.
/// For now, waking a queued Thread is also a fatal error.
inline void TaskingScheduler::thread_suspend_wake( Thread *next ) {
    CHECK( current_thread != master ) << "can't yield on a system Thread";
    CHECK( next->next == NULL ) << "woken Thread should not be on any queue";
    CHECK( !thread_is_running( next ) ) << "woken Thread should not be running";

    Thread * yieldedThr = current_thread;

    current_thread = next;
    thread_context_switch( yieldedThr, next, NULL);
}

/// Make the current Thread idle.
/// Like suspend except the Thread is not blocking on a
/// particular resource, just waiting to be woken.
inline bool TaskingScheduler::thread_idle( uint64_t total_idle ) {
    CHECK( num_idle+1 <= total_idle ) << "number of idle threads should not be more than total"
                                      << " (" << num_idle+1 << " / " << total_idle << ")";
    if (num_idle+1 == total_idle) {
        DVLOG(5) << "going idle and is last";
        return false;
    } else {
        DVLOG(5) << "going idle and is " << num_idle+1 << " of " << total_idle;
        num_idle++;

        unassigned( current_thread );

        thread_suspend( );

        // woke so decrement idle counter
        num_idle--;

        return true;
    }
}

inline bool TaskingScheduler::thread_idle( ) {
    return thread_idle( num_workers );
}

inline void TaskingScheduler::thread_on_exit( ) {
  Thread * exitedThr = current_thread;
  current_thread = master;

  thread_context_switch( exitedThr, master, (void *)exitedThr);
}

#endif

<commit_msg>make sure suspend sets running bit before finding next coro<commit_after>#ifndef _TASKING_SCHEDULER_HPP_
#define _TASKING_SCHEDULER_HPP_

#include "Scheduler.hpp"
#include <Timestamp.hpp>
#include <glog/logging.h>

DECLARE_int64( periodic_poll_ticks );

class TaskManager;
struct task_worker_args;

class TaskingScheduler : public Scheduler {
    private:
        ThreadQueue readyQ;
        ThreadQueue periodicQ;
        ThreadQueue unassignedQ;

        Thread * master;
        Thread * current_thread;
        threadid_t nextId;

        uint64_t num_idle;
        TaskManager * task_manager;
        uint64_t num_workers;

        Thread * getWorker ();

        task_worker_args * work_args;

        // STUB: replace with real periodic threads
        SoftXMT_Timestamp previous_periodic_ts;
        int periodctr;
        Thread * periodicDequeue() {
            // tick the timestap counter
            SoftXMT_tick();
            SoftXMT_Timestamp current_ts = SoftXMT_get_timestamp();

            if( current_ts - previous_periodic_ts > FLAGS_periodic_poll_ticks ) {
                previous_periodic_ts =  current_ts;
                return periodicQ.dequeue();
            } else {
                return NULL;
            }
        }
        //////

        bool queuesFinished();

        Thread * nextCoroutine ( bool isBlocking=true ) {
            do {
                Thread * result;

                // check for periodic tasks
                result = periodicDequeue();
                if (result != NULL) {
                 //   DVLOG(5) << current_thread->id << " scheduler: pick periodic";
                    return result;
                }

                // check ready tasks
                result = readyQ.dequeue();
                if (result != NULL) {
                //    DVLOG(5) << current_thread->id << " scheduler: pick ready";
                    return result;
                }

                // check for new workers
                result = getWorker();
                if (result != NULL) {
                  //  DVLOG(5) << current_thread->id << " scheduler: pick task worker";
                    return result;
                }

                // no coroutines can run, so handle
                /*DVLOG(5) << current_thread->id << " scheduler: no coroutines can run"
                    << "[isBlocking=" << isBlocking
                    << " periodQ=" << (periodicQ.empty() ? "empty" : "full")
                    << " unassignedQ=" << (unassignedQ.empty() ? "empty" : "full") << "]";*/
                usleep(1);
            } while ( isBlocking || !queuesFinished() );
            // exit if all threads exited, including idle workers
            // TODO just as use mightBeWork as shortcut, also kill all idle unassigned workers on cbarrier_exit

            return NULL;
        }

    public:
       TaskingScheduler ( Thread * master, TaskManager * taskman );

       Thread * get_current_thread() {
           return current_thread;
       }

       void assignTid( Thread * thr ) {
           thr->id = nextId++;
       }

      void createWorkers( uint64_t num );
      Thread* maybeSpawnCoroutines( );
      void onWorkerStart( );

       void unassigned( Thread * thr ) {
           unassignedQ.enqueue( thr );
       }

       void ready( Thread * thr ) {
            readyQ.enqueue( thr );
       }

       void periodic( Thread * thr ) {
           periodicQ.enqueue( thr );
       }

       /// run threads until all exit
       void run ( );

       bool thread_yield( );
       bool thread_yield_periodic( );
       void thread_suspend( );
       void thread_wake( Thread * next );
       void thread_yield_wake( Thread * next );
       void thread_suspend_wake( Thread * next );
       bool thread_idle( uint64_t total_idle );
       bool thread_idle( );
       void thread_join( Thread* wait_on );

       // Start running threads from <scheduler> until one dies.  Return that Thread
       // (which can't be restarted--it's trash.)  If <result> non-NULL,
       // store the Thread's exit value there.
       // If no threads to run, returns NULL.
       Thread * thread_wait( void **result );

       void thread_on_exit( );
};

struct task_worker_args {
    TaskManager *const tasks;
    TaskingScheduler *const scheduler;

    task_worker_args( TaskManager * task_manager, TaskingScheduler * sched )
        : tasks( task_manager )
        , scheduler( sched ) { }
};

/// Yield the CPU to the next Thread on your scheduler.  Doesn't ever touch
/// the master Thread.
inline bool TaskingScheduler::thread_yield( ) {
    CHECK( current_thread != master ) << "can't yield on a system Thread";

    ready( current_thread );

    Thread * yieldedThr = current_thread;

    Thread * next = nextCoroutine( );
    bool gotRescheduled = (next == yieldedThr);

    current_thread = next;
    //DVLOG(5) << "Thread " << yieldedThr->id << " yielding to " << next->id << (gotRescheduled ? " (same thread)." : " (diff thread).");
    thread_context_switch( yieldedThr, next, NULL);

    return gotRescheduled; // 0=another ran; 1=me got rescheduled immediately
}

/// For periodic threads: yield the CPU to the next Thread on your scheduler.  Doesn't ever touch
/// the master Thread.
inline bool TaskingScheduler::thread_yield_periodic( ) {
    CHECK( current_thread != master ) << "can't yield on a system Thread";

    periodic( current_thread );

    Thread * yieldedThr = current_thread;

    Thread * next = nextCoroutine( );
    bool gotRescheduled = (next == yieldedThr);

    current_thread = next;
    //DVLOG(5) << "Thread " << yieldedThr->id << " yielding to " << next->id << (gotRescheduled ? " (same thread)." : " (diff thread).");
    thread_context_switch( yieldedThr, next, NULL);

    return gotRescheduled; // 0=another ran; 1=me got rescheduled immediately
}

/// Suspend the current Thread. Thread is not placed on any queue.
inline void TaskingScheduler::thread_suspend( ) {
    CHECK( current_thread != master ) << "can't yield on a system Thread";
    CHECK( thread_is_running(current_thread) ) << "may only suspend a running coroutine";

    Thread * yieldedThr = current_thread;
    yieldedThr->co->running = 0;
    Thread * next = nextCoroutine( );

    current_thread = next;
    thread_context_switch( yieldedThr, next, NULL);
}

/// Wake a suspended Thread by putting it on the run queue.
/// For now, waking a running Thread is a fatal error.
/// For now, waking a queued Thread is also a fatal error.
/// For now, can only wake a Thread on your scheduler
inline void TaskingScheduler::thread_wake( Thread * next ) {
  CHECK( next->sched == this ) << "can only wake a Thread on your scheduler";
  CHECK( next->next == NULL ) << "woken Thread should not be on any queue";
  CHECK( !thread_is_running( next ) ) << "woken Thread should not be running";

  DVLOG(5) << "Thread " << current_thread->id << " wakes thread " << next->id;

  ready( next );
}

/// Yield the current Thread and wake a suspended thread.
/// For now, waking a running Thread is a fatal error.
/// For now, waking a queued Thread is also a fatal error.
inline void TaskingScheduler::thread_yield_wake( Thread * next ) {
    CHECK( current_thread != master ) << "can't yield on a system Thread";
    CHECK( next->sched == this ) << "can only wake a Thread on your scheduler";
    CHECK( next->next == NULL ) << "woken Thread should not be on any queue";
    CHECK( !thread_is_running( next ) ) << "woken Thread should not be running";

    Thread * yieldedThr = current_thread;
    ready( yieldedThr );

    current_thread = next;
    thread_context_switch( yieldedThr, next, NULL);
}

/// Suspend current Thread and wake a suspended thread.
/// For now, waking a running Thread is a fatal error.
/// For now, waking a queued Thread is also a fatal error.
inline void TaskingScheduler::thread_suspend_wake( Thread *next ) {
    CHECK( current_thread != master ) << "can't yield on a system Thread";
    CHECK( next->next == NULL ) << "woken Thread should not be on any queue";
    CHECK( !thread_is_running( next ) ) << "woken Thread should not be running";

    Thread * yieldedThr = current_thread;

    current_thread = next;
    thread_context_switch( yieldedThr, next, NULL);
}

/// Make the current Thread idle.
/// Like suspend except the Thread is not blocking on a
/// particular resource, just waiting to be woken.
inline bool TaskingScheduler::thread_idle( uint64_t total_idle ) {
    CHECK( num_idle+1 <= total_idle ) << "number of idle threads should not be more than total"
                                      << " (" << num_idle+1 << " / " << total_idle << ")";
    if (num_idle+1 == total_idle) {
        DVLOG(5) << "going idle and is last";
        return false;
    } else {
        DVLOG(5) << "going idle and is " << num_idle+1 << " of " << total_idle;
        num_idle++;

        unassigned( current_thread );

        thread_suspend( );

        // woke so decrement idle counter
        num_idle--;

        return true;
    }
}

inline bool TaskingScheduler::thread_idle( ) {
    return thread_idle( num_workers );
}

inline void TaskingScheduler::thread_on_exit( ) {
  Thread * exitedThr = current_thread;
  current_thread = master;

  thread_context_switch( exitedThr, master, (void *)exitedThr);
}

#endif

<|endoftext|>


<commit_before>
/**************************************************************************
 * Copyright(c) 1998-2000, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

#include <TTree.h>
#include <TVector.h>
#include <TObjArray.h>
#include <TFile.h>
#include <TDirectory.h>
#include <TRandom.h>
#include <TArrayI.h>
#include <TH1.h>

#include "AliSTARTDigitizer.h"
#include "AliSTART.h"
#include "AliSTARThit.h"
#include "AliSTARThitPhoton.h"
#include "AliSTARTdigit.h"
#include "AliRunDigitizer.h"
#include "AliHeader.h"
#include "AliGenEventHeader.h"
#include "AliRun.h"
#include "AliPDG.h"
#include "AliLoader.h"
#include "AliRunLoader.h"
#include "AliSTARTLoader.h"

#include <stdlib.h>
#include <Riostream.h>
#include <Riostream.h>

ClassImp(AliSTARTDigitizer)

//___________________________________________
  AliSTARTDigitizer::AliSTARTDigitizer()  :AliDigitizer()
{
// Default ctor - don't use it
  ;
}

//___________________________________________
AliSTARTDigitizer::AliSTARTDigitizer(AliRunDigitizer* manager)
    :AliDigitizer(manager)
{
	cout<<"AliSTARTDigitizer::AliSTARTDigitizer"<<endl;
// ctor which should be used
//  fDebug =0;
 // if (GetDebug()>2)
  //  cerr<<"AliSTARTDigitizer::AliSTARTDigitizer"
   //     <<"(AliRunDigitizer* manager) was processed"<<endl;

}

//------------------------------------------------------------------------
AliSTARTDigitizer::~AliSTARTDigitizer()
{
// Destructor

}

 //------------------------------------------------------------------------
Bool_t AliSTARTDigitizer::Init()
{
// Initialization
 cout<<"AliSTARTDigitizer::Init"<<endl;
 return kTRUE;
}

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

void AliSTARTDigitizer::Exec(Option_t* /*option*/)
{

  AliRunLoader *inRL, *outRL;//in and out Run Loaders
  AliLoader *ingime, *outgime;// in and out ITSLoaders

  outRL = AliRunLoader::GetRunLoader(fManager->GetOutputFolderName());
  outgime = outRL->GetLoader("STARTLoader");

#ifdef DEBUG
  cout<<"AliSTARTDigitizer::>SDigits2Digits start...\n";
#endif
  //
  // From hits to digits
  //
  Int_t hit, nhits;
  Int_t CountEr[13],CountEl[13];							//!!!
  Int_t volume,pmt,tr,tl,sumRight;
  Float_t timediff,timeav;
  Float_t besttimeright,besttimeleft,meanTime;
  Int_t  bestRightADC,bestLeftADC;
  Float_t besttimeleftGaus, besttimerightGaus;
  Float_t timeright[13]={13*0};
  Float_t timeleft[13]={13*0};
  Float_t channelWidth=2.5; //ps
  Int_t channelWidthADC=1; //ps
  //  Int_t thresholdAmpl=10;

  ftimeRightTDC = new TArrayI(12);
  ftimeLeftTDC = new TArrayI(12);
  fRightADC = new TArrayI(12);
  fLeftADC = new TArrayI(12);

  inRL = AliRunLoader::GetRunLoader(fManager->GetInputFolderName(0));
  inRL->LoadgAlice();

  //  fHits = new TClonesArray ("AliSTARThit", 1000);
  fPhotons = new TClonesArray ("AliSTARThitPhoton", 10000);			//!!!
  AliSTART *START  = (AliSTART*) gAlice->GetDetector("START");
  AliSTARThit  *startHit;
  //use if Cherenkov photons
  //  AliSTARThitPhoton  *startHitPhoton;						//!!!
  TBranch *brHits=0;
  TBranch *brHitPhoton=0;
  fdigits= new AliSTARTdigit();

  Int_t nFiles=fManager->GetNinputs();
  for (Int_t inputFile=0; inputFile<nFiles;  inputFile++) {

    besttimeright=9999.;
    besttimeleft=9999.;
    Int_t timeDiff=0;
    Int_t timeAv=0;
    sumRight=0;
    for (Int_t i0=0; i0<13; i0++)
      {
	timeright[i0]=0; timeleft[i0]=0;
	CountEr[i0]=0;   CountEl[i0]=0;
      }

    inRL = AliRunLoader::GetRunLoader(fManager->GetInputFolderName(inputFile));
    ingime = inRL->GetLoader("STARTLoader");
    ingime->LoadHits("READ");//probably it is necessary to load them before
    ingime->LoadDigits("UPDATE");//probably it is necessary to load them before
    //use if Cherenkov photons
    //  TClonesArray *STARThitsPhotons = START->Photons ();
    TClonesArray *fHits = START->Hits ();
    //    cout<<" Load  "<<AliSTARTLoader::LoadDigits()<<endl;

    TTree *th = ingime->TreeH();
    brHits = th->GetBranch("START");
    brHitPhoton = th->GetBranch("STARThitPhoton");
    if (brHits) {
      START->SetHitsAddressBranch(brHits,brHitPhoton);
    }else{
      cerr<<"EXEC Branch START hit not found"<<endl;
      exit(111);
    }
    Int_t ntracks    = (Int_t) th->GetEntries();
    cout<<" ntracks "<<ntracks<<endl;
    if (ntracks<=0) return;
    // Start loop on tracks in the photon hits containers
    // for amplitude
    /*
    if(brHitPhoton) {
      cout<<"brHitPhoton "<<endl;
      for (Int_t track=0; track<ntracks;track++) {
	brHitPhoton -> GetEntry(track);;
	nhits = STARThitsPhotons->GetEntriesFast();
	for (hit=0;hit<nhits;hit++) {
	  startHitPhoton   = (AliSTARThitPhoton*)
	   STARThitsPhotons ->UncheckedAt(hit);
	  pmt=startHitPhoton->fPmt;
	  volume = startHitPhoton->fArray;
	  if(RegisterPhotoE(startHitPhoton))
	    {
	      if (volume == 1) CountEr[pmt]++;
	      if (volume == 2) CountEl[pmt]++;
	    }
	} //hit photons
      } //track photons
    } // was photons
    */
    // Start loop on tracks in the hits containers
    for (Int_t track=0; track<ntracks;track++) {
      brHits->GetEntry(track);
      nhits = fHits->GetEntriesFast();
      //  cout<<" brHits hits "<<nhits<<endl;
      for (hit=0;hit<nhits;hit++) {
	startHit   = (AliSTARThit*) fHits->UncheckedAt(hit);
	pmt=startHit->Pmt();
	volume = startHit->Volume();
	if(volume==1){
	  timeright[pmt] = startHit->Time();
	  if(timeright[pmt]<besttimeright)
	    //&&CountEr[pmt-1]>thresholdAmpl)
	    {
	    besttimeright=timeright[pmt];
	  } //timeright
	}//time for right shoulder
	if(volume==2){
	  timeleft[pmt] = startHit->Time();
	  if(timeleft[pmt]<besttimeleft)
	    //&&CountEl[pmt-1]>thresholdAmpl)
	    {
	    besttimeleft=timeleft[pmt];

	  } //timeleftbest
	}//time for left shoulder
      } //hit loop
    } //track loop

    // z position
    cout<<" right time  "<<besttimeright<<
      " right distance "<<besttimeright*30<<endl;;
    cout<<" left time  "<<besttimeleft<<
      " left distance "<<besttimeleft*30<<endl;;

    //folding with experimental time distribution

    besttimeleftGaus=gRandom->Gaus(besttimeright,0.05);
    cout<<" besttimeleftGaus "<<besttimeleftGaus<<endl;
    bestLeftADC=Int_t (besttimeleftGaus*1000/channelWidth);
    Float_t koef=69.7/350.;
    besttimeright=koef*besttimeleft;
    besttimerightGaus=gRandom->Gaus(besttimeleft,0.05);

    bestRightADC=Int_t (besttimerightGaus*1000/channelWidth);
    timediff=besttimerightGaus-besttimeleftGaus;
    cout<<" timediff in ns "<<timediff<<" z= "<<timediff*30<<endl;
    meanTime=(besttimerightGaus+besttimeleftGaus)/2.;
    if ( TMath::Abs(timediff)<TMath::Abs(0.3) )
      {
	Float_t t1=1000.*besttimeleftGaus;
	Float_t t2=1000.*besttimerightGaus;
	t1=t1/channelWidth;   //time in ps to channelWidth
	t2=t2/channelWidth;   //time in ps to channelWidth
	timeav=(t1+t2)/2.;

	// Time to TDC signal
	// 256 channels for timediff, range 1ns

	timediff=512+1000*timediff/channelWidth; // time in ps

	timeAv = (Int_t)(timeav);   // time  channel numbres
	timeDiff = (Int_t)(timediff); // time  channel numbres
	//       fill digits
	fdigits->SetTimeBestLeft(bestLeftADC);
	fdigits->SetTimeBestRight(bestRightADC);
	fdigits->SetMeanTime(timeAv);
	fdigits->SetTimeDiff(timeDiff);
	for (Int_t i=0; i<12; i++)
	  {
	    //  fill TDC
	    timeright[i+1]=gRandom->Gaus(timeright[i+1],0.05);
	    timeleft[i+1]=gRandom->Gaus(timeleft[i+1],0.05);
	    tr= Int_t (timeright[i+1]*1000/channelWidth);
	    if(tr<200) tr=0;
	    tl= Int_t (timeleft[i+1]*1000/channelWidth);
	    if(tl<1000) tl=0;

	    ftimeRightTDC->AddAt(tr,i);
	    ftimeLeftTDC->AddAt(tl,i);
	    //fill ADC
	    Int_t al=( Int_t ) CountEl[i+1]/ channelWidthADC;
	    Int_t ar=( Int_t ) CountEr[i+1]/ channelWidthADC;
	    fRightADC->AddAt(ar,i);
	    fLeftADC ->AddAt(al,i);
	    sumRight+=CountEr[i+1];
	  }
	fdigits->SetTimeRight(*ftimeRightTDC);
	fdigits->SetTimeLeft(*ftimeLeftTDC);
	fdigits->SetADCRight(*fRightADC);
	fdigits->SetADCLeft(*fLeftADC);
	// cout<<" before sum"<<endl;
	fdigits->SetSumADCRight(sumRight);
      }
    else
      {timeAv=999999; timeDiff=99999;}

// trick to find out output dir:

/*
   // trick to find out output dir:
    TTree *outTree = fManager->GetTreeD();
    if (!outTree) {
      cerr<<"something wrong with output...."<<endl;
      exit(111);
    }

    Char_t nameDigits[20];
    TDirectory *wd = gDirectory;
    outTree->GetDirectory()->cd();
    fdigits->Write(nameDigits);
    cout<<nameDigits<<endl;
    wd->cd();
*/

     Char_t nameDigits[20];
    sprintf(nameDigits,"START_D_%d",fManager->GetOutputEventNr());
    fdigits->Write(nameDigits);

    //    outgime->WriteDigits("OVERWRITE");
  }
}

//------------------------------------------------------------------------
Bool_t AliSTARTDigitizer::RegisterPhotoE(/*AliSTARThitPhoton *hit*/)
{
    Double_t    P = 0.2;
    Double_t    p;

    p = gRandom->Rndm();
    if (p > P)
      return kFALSE;

    return kTRUE;
}
//----------------------------------------------------------------------------
<commit_msg>Protection in case of missing hit (alpha)<commit_after>
/**************************************************************************
 * Copyright(c) 1998-2000, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

#include <TTree.h>
#include <TVector.h>
#include <TObjArray.h>
#include <TFile.h>
#include <TDirectory.h>
#include <TRandom.h>
#include <TArrayI.h>
#include <TH1.h>
#include <TError.h>

#include "AliSTARTDigitizer.h"
#include "AliSTART.h"
#include "AliSTARThit.h"
#include "AliSTARThitPhoton.h"
#include "AliSTARTdigit.h"
#include "AliRunDigitizer.h"
#include "AliHeader.h"
#include "AliGenEventHeader.h"
#include "AliRun.h"
#include "AliPDG.h"
#include "AliLoader.h"
#include "AliRunLoader.h"
#include "AliSTARTLoader.h"

#include <stdlib.h>
#include <Riostream.h>
#include <Riostream.h>

ClassImp(AliSTARTDigitizer)

//___________________________________________
  AliSTARTDigitizer::AliSTARTDigitizer()  :AliDigitizer()
{
// Default ctor - don't use it
  ;
}

//___________________________________________
AliSTARTDigitizer::AliSTARTDigitizer(AliRunDigitizer* manager)
    :AliDigitizer(manager)
{
	cout<<"AliSTARTDigitizer::AliSTARTDigitizer"<<endl;
// ctor which should be used
//  fDebug =0;
 // if (GetDebug()>2)
  //  cerr<<"AliSTARTDigitizer::AliSTARTDigitizer"
   //     <<"(AliRunDigitizer* manager) was processed"<<endl;

}

//------------------------------------------------------------------------
AliSTARTDigitizer::~AliSTARTDigitizer()
{
// Destructor

}

 //------------------------------------------------------------------------
Bool_t AliSTARTDigitizer::Init()
{
// Initialization
 cout<<"AliSTARTDigitizer::Init"<<endl;
 return kTRUE;
}

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

void AliSTARTDigitizer::Exec(Option_t* /*option*/)
{

  AliRunLoader *inRL, *outRL;//in and out Run Loaders
  AliLoader *ingime, *outgime;// in and out ITSLoaders

  outRL = AliRunLoader::GetRunLoader(fManager->GetOutputFolderName());
  outgime = outRL->GetLoader("STARTLoader");

#ifdef DEBUG
  cout<<"AliSTARTDigitizer::>SDigits2Digits start...\n";
#endif
  //
  // From hits to digits
  //
  Int_t hit, nhits;
  Int_t CountEr[13],CountEl[13];							//!!!
  Int_t volume,pmt,tr,tl,sumRight;
  Float_t timediff,timeav;
  Float_t besttimeright,besttimeleft,meanTime;
  Int_t  bestRightADC,bestLeftADC;
  Float_t besttimeleftGaus, besttimerightGaus;
  Float_t timeright[13]={13*0};
  Float_t timeleft[13]={13*0};
  Float_t channelWidth=2.5; //ps
  Int_t channelWidthADC=1; //ps
  //  Int_t thresholdAmpl=10;

  ftimeRightTDC = new TArrayI(12);
  ftimeLeftTDC = new TArrayI(12);
  fRightADC = new TArrayI(12);
  fLeftADC = new TArrayI(12);

  inRL = AliRunLoader::GetRunLoader(fManager->GetInputFolderName(0));
  inRL->LoadgAlice();

  //  fHits = new TClonesArray ("AliSTARThit", 1000);
  fPhotons = new TClonesArray ("AliSTARThitPhoton", 10000);			//!!!
  AliSTART *START  = (AliSTART*) gAlice->GetDetector("START");
  AliSTARThit  *startHit;
  //use if Cherenkov photons
  //  AliSTARThitPhoton  *startHitPhoton;						//!!!
  TBranch *brHits=0;
  TBranch *brHitPhoton=0;
  fdigits= new AliSTARTdigit();

  Int_t nFiles=fManager->GetNinputs();
  for (Int_t inputFile=0; inputFile<nFiles;  inputFile++) {

    besttimeright=9999.;
    besttimeleft=9999.;
    Int_t timeDiff=0;
    Int_t timeAv=0;
    sumRight=0;
    for (Int_t i0=0; i0<13; i0++)
      {
	timeright[i0]=0; timeleft[i0]=0;
	CountEr[i0]=0;   CountEl[i0]=0;
      }

    inRL = AliRunLoader::GetRunLoader(fManager->GetInputFolderName(inputFile));
    ingime = inRL->GetLoader("STARTLoader");
    ingime->LoadHits("READ");//probably it is necessary to load them before
    ingime->LoadDigits("UPDATE");//probably it is necessary to load them before
    //use if Cherenkov photons
    //  TClonesArray *STARThitsPhotons = START->Photons ();
    TClonesArray *fHits = START->Hits ();
    //    cout<<" Load  "<<AliSTARTLoader::LoadDigits()<<endl;

    TTree *th = ingime->TreeH();
    brHits = th->GetBranch("START");
    brHitPhoton = th->GetBranch("STARThitPhoton");
    if (brHits) {
      START->SetHitsAddressBranch(brHits,brHitPhoton);
    }else{
      cerr<<"EXEC Branch START hit not found"<<endl;
      exit(111);
    }
    Int_t ntracks    = (Int_t) th->GetEntries();
    cout<<" ntracks "<<ntracks<<endl;
    if (ntracks<=0) return;
    // Start loop on tracks in the photon hits containers
    // for amplitude
    /*
    if(brHitPhoton) {
      cout<<"brHitPhoton "<<endl;
      for (Int_t track=0; track<ntracks;track++) {
	brHitPhoton -> GetEntry(track);;
	nhits = STARThitsPhotons->GetEntriesFast();
	for (hit=0;hit<nhits;hit++) {
	  startHitPhoton   = (AliSTARThitPhoton*)
	   STARThitsPhotons ->UncheckedAt(hit);
	  pmt=startHitPhoton->fPmt;
	  volume = startHitPhoton->fArray;
	  if(RegisterPhotoE(startHitPhoton))
	    {
	      if (volume == 1) CountEr[pmt]++;
	      if (volume == 2) CountEl[pmt]++;
	    }
	} //hit photons
      } //track photons
    } // was photons
    */
    // Start loop on tracks in the hits containers
    for (Int_t track=0; track<ntracks;track++) {
      brHits->GetEntry(track);
      nhits = fHits->GetEntriesFast();
      //  cout<<" brHits hits "<<nhits<<endl;
      for (hit=0;hit<nhits;hit++) {
	startHit   = (AliSTARThit*) fHits->UncheckedAt(hit);
	if (!startHit) {
	  ::Error("Exec","The unchecked hit doesn't exist");
	  break;
	}
	pmt=startHit->Pmt();
	volume = startHit->Volume();
	if(volume==1){
	  timeright[pmt] = startHit->Time();
	  if(timeright[pmt]<besttimeright)
	    //&&CountEr[pmt-1]>thresholdAmpl)
	    {
	    besttimeright=timeright[pmt];
	  } //timeright
	}//time for right shoulder
	if(volume==2){
	  timeleft[pmt] = startHit->Time();
	  if(timeleft[pmt]<besttimeleft)
	    //&&CountEl[pmt-1]>thresholdAmpl)
	    {
	    besttimeleft=timeleft[pmt];

	  } //timeleftbest
	}//time for left shoulder
      } //hit loop
    } //track loop

    // z position
    cout<<" right time  "<<besttimeright<<
      " right distance "<<besttimeright*30<<endl;;
    cout<<" left time  "<<besttimeleft<<
      " left distance "<<besttimeleft*30<<endl;;

    //folding with experimental time distribution

    besttimeleftGaus=gRandom->Gaus(besttimeright,0.05);
    cout<<" besttimeleftGaus "<<besttimeleftGaus<<endl;
    bestLeftADC=Int_t (besttimeleftGaus*1000/channelWidth);
    Float_t koef=69.7/350.;
    besttimeright=koef*besttimeleft;
    besttimerightGaus=gRandom->Gaus(besttimeleft,0.05);

    bestRightADC=Int_t (besttimerightGaus*1000/channelWidth);
    timediff=besttimerightGaus-besttimeleftGaus;
    cout<<" timediff in ns "<<timediff<<" z= "<<timediff*30<<endl;
    meanTime=(besttimerightGaus+besttimeleftGaus)/2.;
    if ( TMath::Abs(timediff)<TMath::Abs(0.3) )
      {
	Float_t t1=1000.*besttimeleftGaus;
	Float_t t2=1000.*besttimerightGaus;
	t1=t1/channelWidth;   //time in ps to channelWidth
	t2=t2/channelWidth;   //time in ps to channelWidth
	timeav=(t1+t2)/2.;

	// Time to TDC signal
	// 256 channels for timediff, range 1ns

	timediff=512+1000*timediff/channelWidth; // time in ps

	timeAv = (Int_t)(timeav);   // time  channel numbres
	timeDiff = (Int_t)(timediff); // time  channel numbres
	//       fill digits
	fdigits->SetTimeBestLeft(bestLeftADC);
	fdigits->SetTimeBestRight(bestRightADC);
	fdigits->SetMeanTime(timeAv);
	fdigits->SetTimeDiff(timeDiff);
	for (Int_t i=0; i<12; i++)
	  {
	    //  fill TDC
	    timeright[i+1]=gRandom->Gaus(timeright[i+1],0.05);
	    timeleft[i+1]=gRandom->Gaus(timeleft[i+1],0.05);
	    tr= Int_t (timeright[i+1]*1000/channelWidth);
	    if(tr<200) tr=0;
	    tl= Int_t (timeleft[i+1]*1000/channelWidth);
	    if(tl<1000) tl=0;

	    ftimeRightTDC->AddAt(tr,i);
	    ftimeLeftTDC->AddAt(tl,i);
	    //fill ADC
	    Int_t al=( Int_t ) CountEl[i+1]/ channelWidthADC;
	    Int_t ar=( Int_t ) CountEr[i+1]/ channelWidthADC;
	    fRightADC->AddAt(ar,i);
	    fLeftADC ->AddAt(al,i);
	    sumRight+=CountEr[i+1];
	  }
	fdigits->SetTimeRight(*ftimeRightTDC);
	fdigits->SetTimeLeft(*ftimeLeftTDC);
	fdigits->SetADCRight(*fRightADC);
	fdigits->SetADCLeft(*fLeftADC);
	// cout<<" before sum"<<endl;
	fdigits->SetSumADCRight(sumRight);
      }
    else
      {timeAv=999999; timeDiff=99999;}

// trick to find out output dir:

/*
   // trick to find out output dir:
    TTree *outTree = fManager->GetTreeD();
    if (!outTree) {
      cerr<<"something wrong with output...."<<endl;
      exit(111);
    }

    Char_t nameDigits[20];
    TDirectory *wd = gDirectory;
    outTree->GetDirectory()->cd();
    fdigits->Write(nameDigits);
    cout<<nameDigits<<endl;
    wd->cd();
*/

     Char_t nameDigits[20];
    sprintf(nameDigits,"START_D_%d",fManager->GetOutputEventNr());
    fdigits->Write(nameDigits);

    //    outgime->WriteDigits("OVERWRITE");
  }
}

//------------------------------------------------------------------------
Bool_t AliSTARTDigitizer::RegisterPhotoE(/*AliSTARThitPhoton *hit*/)
{
    Double_t    P = 0.2;
    Double_t    p;

    p = gRandom->Rndm();
    if (p > P)
      return kFALSE;

    return kTRUE;
}
//----------------------------------------------------------------------------
<|endoftext|>


<commit_before>#include <fstream>
#include <GL/glew.h>
#include "BMPResource.h"
#include "Debug.h"

namespace sark{

	BMPResource::BMPResource()
		: mWidth(0), mHeight(0), mPixels(NULL)
	{}
	BMPResource::BMPResource(const BMPResource& bmp)
		: mWidth(bmp.mWidth), mHeight(bmp.mHeight)
	{
		integer size = bmp.mWidth * bmp.mHeight * 3;
		mPixels = new uint8[size];
		memcpy(mPixels, bmp.mPixels, size);
	}

	BMPResource::~BMPResource(){
		if (mPixels != NULL){
			delete[] mPixels;
		}
	}

	const integer BMPResource::GetWidth() const{
		return mWidth;
	}

	const integer BMPResource::GetHeight() const{
		return mHeight;
	}

	const integer BMPResource::GetDepth() const{
		return 0;
	}

	Texture::Format BMPResource::GetPixelFormat() const{
		return Texture::Format::RGB;
	}

	Texture::PixelType BMPResource::GetPixelType() const{
		return Texture::PixelType::UNSIGNED_BYTE;
	}

	const void* BMPResource::GetPixels() const{
		return mPixels;
	}

	BMPResource* BMPResource::LoadImp(const std::string& name){
		BITMAPFILEHEADER bmpFileHead;
		BITMAPINFOHEADER bmpInfoHead;
		memset(&bmpFileHead, 0, sizeof(BITMAPFILEHEADER));
		memset(&bmpInfoHead, 0, sizeof(BITMAPINFOHEADER));

		std::ifstream stream;
		stream.open(name, std::ios::binary | std::ios::beg);
		if (!stream.is_open()){
			LogWarn(name + " would not open");
			return NULL;
		}

		stream.read((char*)&bmpFileHead, sizeof(BITMAPFILEHEADER));
		if (((char*)&bmpFileHead)[0] != 'B' || ((char*)&bmpFileHead)[1] != 'M'){
			LogWarn(name + " has invalid bitmap magic-code");
			return NULL;
		}

		stream.read((char*)&bmpInfoHead, sizeof(BITMAPINFOHEADER));
		if (bmpInfoHead.biSize != 40){
			LogWarn("it only support BITMAPINFOHEADER format bitmap");
			return NULL;
		}

		if (bmpInfoHead.biBitCount != 24 && bmpInfoHead.biBitCount != 32){
			LogWarn(name + " has unsupported bit-count")
				return NULL;
		}

		BMPResource* bmp = new BMPResource();
		bmp->mWidth = bmpInfoHead.biWidth;
		bmp->mHeight = bmpInfoHead.biHeight;
		bmp->mPixels = new uint8[bmp->mWidth * bmp->mHeight * 3];

		stream.seekg(bmpFileHead.bfOffBits, std::ios::beg);
		if (bmpInfoHead.biBitCount == 24){
			// 24bit bmp has dummy pixels in each rows
			integer dumbyte = ((bmp->mWidth) % 4);
			dumbyte = (dumbyte == 0 ? 0 : (4 - dumbyte) * 3);

			int64 i, k;
			for (i = 0; i < bmp->mHeight; i++){
				for (k = 0; k < bmp->mWidth; k++){
					// read bgr order
					int64 pix_idx = (bmp->mHeight - i - 1)*bmp->mWidth * 3 + k * 3;
					stream.read((char*)&bmp->mPixels[pix_idx], 3);

					uint8 t = bmp->mPixels[pix_idx];
					bmp->mPixels[pix_idx] = bmp->mPixels[pix_idx + 2];
					bmp->mPixels[pix_idx + 2] = t;
				}
				stream.seekg(dumbyte, std::ios::cur);
			}
		}
		else if (bmpInfoHead.biBitCount == 32){
			uint8 rgba[4];
			int64 i, k;
			for (i = 0; i < bmp->mHeight; i++){
				for (k = 0; k < bmp->mWidth; k++){
					// read rgba order
					stream.read((char*)rgba, 4);

					int64 pix_idx = (bmp->mHeight - i - 1)*bmp->mWidth * 3 + k * 3;
					bmp->mPixels[pix_idx] = rgba[0];
					bmp->mPixels[pix_idx+1] = rgba[1];
					bmp->mPixels[pix_idx+2] = rgba[2];
					// alpha value is discarded
				}
			}
		}
		return bmp;
	}

}<commit_msg>minor bug. ';' is missing..<commit_after>#include <fstream>
#include <GL/glew.h>
#include "BMPResource.h"
#include "Debug.h"

namespace sark{

	BMPResource::BMPResource()
		: mWidth(0), mHeight(0), mPixels(NULL)
	{}
	BMPResource::BMPResource(const BMPResource& bmp)
		: mWidth(bmp.mWidth), mHeight(bmp.mHeight)
	{
		integer size = bmp.mWidth * bmp.mHeight * 3;
		mPixels = new uint8[size];
		memcpy(mPixels, bmp.mPixels, size);
	}

	BMPResource::~BMPResource(){
		if (mPixels != NULL){
			delete[] mPixels;
		}
	}

	const integer BMPResource::GetWidth() const{
		return mWidth;
	}

	const integer BMPResource::GetHeight() const{
		return mHeight;
	}

	const integer BMPResource::GetDepth() const{
		return 0;
	}

	Texture::Format BMPResource::GetPixelFormat() const{
		return Texture::Format::RGB;
	}

	Texture::PixelType BMPResource::GetPixelType() const{
		return Texture::PixelType::UNSIGNED_BYTE;
	}

	const void* BMPResource::GetPixels() const{
		return mPixels;
	}

	BMPResource* BMPResource::LoadImp(const std::string& name){
		BITMAPFILEHEADER bmpFileHead;
		BITMAPINFOHEADER bmpInfoHead;
		memset(&bmpFileHead, 0, sizeof(BITMAPFILEHEADER));
		memset(&bmpInfoHead, 0, sizeof(BITMAPINFOHEADER));

		std::ifstream stream;
		stream.open(name, std::ios::binary | std::ios::beg);
		if (!stream.is_open()){
			LogWarn(name + " would not open");
			return NULL;
		}

		stream.read((char*)&bmpFileHead, sizeof(BITMAPFILEHEADER));
		if (((char*)&bmpFileHead)[0] != 'B' || ((char*)&bmpFileHead)[1] != 'M'){
			LogWarn(name + " has invalid bitmap magic-code");
			return NULL;
		}

		stream.read((char*)&bmpInfoHead, sizeof(BITMAPINFOHEADER));
		if (bmpInfoHead.biSize != 40){
			LogWarn("it only support BITMAPINFOHEADER format bitmap");
			return NULL;
		}

		if (bmpInfoHead.biBitCount != 24 && bmpInfoHead.biBitCount != 32){
			LogWarn(name + " has unsupported bit-count");
				return NULL;
		}

		BMPResource* bmp = new BMPResource();
		bmp->mWidth = bmpInfoHead.biWidth;
		bmp->mHeight = bmpInfoHead.biHeight;
		bmp->mPixels = new uint8[bmp->mWidth * bmp->mHeight * 3];

		stream.seekg(bmpFileHead.bfOffBits, std::ios::beg);
		if (bmpInfoHead.biBitCount == 24){
			// 24bit bmp has dummy pixels in each rows
			integer dumbyte = ((bmp->mWidth) % 4);
			dumbyte = (dumbyte == 0 ? 0 : (4 - dumbyte) * 3);

			int64 i, k;
			for (i = 0; i < bmp->mHeight; i++){
				for (k = 0; k < bmp->mWidth; k++){
					// read bgr order
					int64 pix_idx = (bmp->mHeight - i - 1)*bmp->mWidth * 3 + k * 3;
					stream.read((char*)&bmp->mPixels[pix_idx], 3);

					uint8 t = bmp->mPixels[pix_idx];
					bmp->mPixels[pix_idx] = bmp->mPixels[pix_idx + 2];
					bmp->mPixels[pix_idx + 2] = t;
				}
				stream.seekg(dumbyte, std::ios::cur);
			}
		}
		else if (bmpInfoHead.biBitCount == 32){
			uint8 rgba[4];
			int64 i, k;
			for (i = 0; i < bmp->mHeight; i++){
				for (k = 0; k < bmp->mWidth; k++){
					// read rgba order
					stream.read((char*)rgba, 4);

					int64 pix_idx = (bmp->mHeight - i - 1)*bmp->mWidth * 3 + k * 3;
					bmp->mPixels[pix_idx] = rgba[0];
					bmp->mPixels[pix_idx+1] = rgba[1];
					bmp->mPixels[pix_idx+2] = rgba[2];
					// alpha value is discarded
				}
			}
		}
		return bmp;
	}

}<|endoftext|>


<commit_before>//-----------------------------------------------
//
//	This file is part of the Siv3D Engine.
//
//	Copyright (c) 2008-2021 Ryo Suzuki
//	Copyright (c) 2016-2021 OpenSiv3D Project
//
//	Licensed under the MIT License.
//
//-----------------------------------------------

# pragma once
# include "Common.hpp"
# include "StringView.hpp"

# if SIV3D_PLATFORM(WINDOWS)

# include <Siv3D/Windows/Windows.hpp>

namespace s3d
{
	using LibraryHandle = HMODULE;

	namespace DLL
	{
		[[nodiscard]]
		LibraryHandle LoadSystemLibraryNoThrow(const wchar_t* library);

		[[nodiscard]]
		LibraryHandle LoadSystemLibrary(const wchar_t* library);

		[[nodiscard]]
		LibraryHandle Load(StringView path);

		void Unload(LibraryHandle& library);

		class GetFunctionNoThrow
		{
		public:

			SIV3D_NODISCARD_CXX20
			GetFunctionNoThrow(LibraryHandle _module, const char* name);

			template <class Type>
			operator Type() const noexcept
			{
				return static_cast<Type>(p);
			}

		private:

			const void* p;
		};

		class GetFunction
		{
		public:

			SIV3D_NODISCARD_CXX20
			GetFunction(LibraryHandle _module, const char* name);

			template <class Type>
			operator Type() const noexcept
			{
				return static_cast<Type>(p);
			}

		private:

			const void* p;
		};
	}
}

# endif

# if SIV3D_PLATFORM(MACOS) || SIV3D_PLATFORM(LINUX)

# include <dlfcn.h>

namespace s3d
{
	using LibraryHandle = void*;

	namespace DLL
	{
		[[nodiscard]]
		LibraryHandle Load(StringView path);

		void Unload(LibraryHandle& library);

		class GetFunctionNoThrow
		{
		public:

			SIV3D_NODISCARD_CXX20
			GetFunctionNoThrow(LibraryHandle _module, const char* name);

			template <class Type>
			operator Type() const noexcept
			{
				return reinterpret_cast<Type>(p);
			}

		private:

			void* p;
		};

		class GetFunction
		{
		public:

			SIV3D_NODISCARD_CXX20
			GetFunction(LibraryHandle _module, const char* name);

			template <class Type>
			operator Type() const noexcept
			{
				return reinterpret_cast<Type>(p);
			}

		private:

			void* p;
		};
	}
}

# endif
<commit_msg>[共通] SivDLL Web版の処理追加<commit_after>//-----------------------------------------------
//
//	This file is part of the Siv3D Engine.
//
//	Copyright (c) 2008-2021 Ryo Suzuki
//	Copyright (c) 2016-2021 OpenSiv3D Project
//
//	Licensed under the MIT License.
//
//-----------------------------------------------

# pragma once
# include "Common.hpp"
# include "StringView.hpp"

# if SIV3D_PLATFORM(WINDOWS)

# include <Siv3D/Windows/Windows.hpp>

namespace s3d
{
	using LibraryHandle = HMODULE;

	namespace DLL
	{
		[[nodiscard]]
		LibraryHandle LoadSystemLibraryNoThrow(const wchar_t* library);

		[[nodiscard]]
		LibraryHandle LoadSystemLibrary(const wchar_t* library);

		[[nodiscard]]
		LibraryHandle Load(StringView path);

		void Unload(LibraryHandle& library);

		class GetFunctionNoThrow
		{
		public:

			SIV3D_NODISCARD_CXX20
			GetFunctionNoThrow(LibraryHandle _module, const char* name);

			template <class Type>
			operator Type() const noexcept
			{
				return static_cast<Type>(p);
			}

		private:

			const void* p;
		};

		class GetFunction
		{
		public:

			SIV3D_NODISCARD_CXX20
			GetFunction(LibraryHandle _module, const char* name);

			template <class Type>
			operator Type() const noexcept
			{
				return static_cast<Type>(p);
			}

		private:

			const void* p;
		};
	}
}

# endif

# if SIV3D_PLATFORM(MACOS) || SIV3D_PLATFORM(LINUX) || SIV3D_PLATFORM(WEB)

# include <dlfcn.h>

namespace s3d
{
	using LibraryHandle = void*;

	namespace DLL
	{
		[[nodiscard]]
		LibraryHandle Load(StringView path);

		void Unload(LibraryHandle& library);

		class GetFunctionNoThrow
		{
		public:

			SIV3D_NODISCARD_CXX20
			GetFunctionNoThrow(LibraryHandle _module, const char* name);

			template <class Type>
			operator Type() const noexcept
			{
				return reinterpret_cast<Type>(p);
			}

		private:

			void* p;
		};

		class GetFunction
		{
		public:

			SIV3D_NODISCARD_CXX20
			GetFunction(LibraryHandle _module, const char* name);

			template <class Type>
			operator Type() const noexcept
			{
				return reinterpret_cast<Type>(p);
			}

		private:

			void* p;
		};
	}
}

# endif
<|endoftext|>


<commit_before>#include <thread>
#include "TcpClient.h"
#include "platform/CCFileUtils.h"
#include "base/CCDirector.h"
#include "base/CCScheduler.h"
#include "2d/CCLabel.h"
#include "../../PacketType.h"
#include "SingleGameScene.h"
#include "ObjectLayer.h"
#include "NetworkScene.h"
#include "LoadingBGLayer.h"
#include "RoomScene.h"
#include "MultiGameScene.h"

#ifdef _WIN32
#pragma comment(lib,"ws2_32.lib")
#define sleep(x) Sleep(x)
#endif

static TcpClient* s_TcpClient = nullptr;

TcpClient::TcpClient() : mRecvBuffer(BUF_SIZE), mSock(NULL), mLoginId(-1)
{
	///
	auto t = std::thread(CC_CALLBACK_0(TcpClient::networkThread, this));
	t.detach();
}

TcpClient::~TcpClient()
{
	if(mSock == NULL)
		return;

#ifndef _WIN32
	close(mSock);
#else
	closesocket(mSock);
	WSACleanup();
#endif
}

TcpClient* TcpClient::getInstance()
{
	if (nullptr == s_TcpClient)
	{
		s_TcpClient = new TcpClient();
	}
	return s_TcpClient;
}

void TcpClient::destroyInstance()
{
	CC_SAFE_DELETE(s_TcpClient);
}

///////////////////////////////////////////////////////////////////////////
/*
	 ,  Լ
*/
///////////////////////////////////////////////////////////////////////////
bool TcpClient::connect()
{
	if (mSock != NULL)
	{
		TcpClient::getInstance()->disconnect();
	}

#ifdef _WIN32
	WSADATA wsa;
	if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
		return false;
#endif

	mSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (mSock == INVALID_SOCKET)
		return false;

	std::string ipaddr = cocos2d::UserDefault::getInstance()->getStringForKey("ipaddr", std::string("localhost"));
	int port = cocos2d::UserDefault::getInstance()->getIntegerForKey("port", 9001);

	struct hostent* host;
	struct sockaddr_in hostAddr;

	if ((host = gethostbyname(ipaddr.c_str())) == 0)
		return false;

	memset(&hostAddr, 0, sizeof(hostAddr));
	hostAddr.sin_family = AF_INET;
	hostAddr.sin_addr.s_addr = inet_addr("10.73.38.181");
	hostAddr.sin_port = htons(port);

	if (SOCKET_ERROR == ::connect(mSock, (struct sockaddr*)&hostAddr, sizeof(hostAddr)))
	{
		CCLOG("CONNECT FAILED");
		return false;
	}

	/// nagle ˰
	int opt = 1;
	setsockopt(mSock, IPPROTO_TCP, TCP_NODELAY, (const char*)&opt, sizeof(int));

	return true;
}

void TcpClient::disconnect()
{
	if (mSock == NULL)
		return;

#ifndef _WIN32
	close(mSock);
#else
	closesocket(mSock);
	WSACleanup();
#endif
	mSock = NULL;
	mLoginId = -1;

	return;
}

///////////////////////////////////////////////////////////////////////////
/*
	 Ŷ , ޴ Լ
*/
///////////////////////////////////////////////////////////////////////////
bool TcpClient::send(const char* data, int length)
{
	int count = 0;
	while (count < length)
	{
		int n = ::send(mSock, data + count, length, 0);
		if (n == SOCKET_ERROR)
		{
			CCLOG("SEND ERROR");
			return false;
		}
		count += n;
		length -= n;
	}

	return true;
}

void TcpClient::networkThread()
{
	while ( true )
	{
		char inBuf[4096] = { 0, };

		int n = ::recv(mSock, inBuf, 4096, 0);

		if (n < 1)
		{
			sleep(0); ///< for cpu low-utilization
			continue;
		}

		if (!mRecvBuffer.Write(inBuf, n))
		{
			///  á.
			assert(false);
		}

		processPacket();
	}
}

///////////////////////////////////////////////////////////////////////////
/*
	 Ŷ ĽϿ óϴ Լ
*/
///////////////////////////////////////////////////////////////////////////
void TcpClient::processPacket()
{
	auto scheduler = cocos2d::Director::getInstance()->getScheduler();

	/// Ŷ Ľؼ ϼǴ Ŷ , ش ݹ ҷش.
	while (true)
	{
		PacketHeader header;

		if (false == mRecvBuffer.Peek((char*)&header, sizeof(PacketHeader)))
			break;

		if (header.mSize > mRecvBuffer.GetStoredSize())
			break;

		switch (header.mType)
		{
		case PKT_SC_LOGIN:
			{
				LoginResult recvData;
				bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize);
				assert(ret && recvData.mPlayerId != -1);

				mLoginId = recvData.mPlayerId;

				auto layer = cocos2d::Director::getInstance()->getRunningScene()->getChildByName("NetworkScene");
				if (layer == nullptr)
					break;

				scheduler->performFunctionInCocosThread(CC_CALLBACK_0(NetworkScene::ConnectComplete, dynamic_cast<NetworkScene*>(layer)));
			}
			break;
		case PKT_SC_MAKE_ROOM:
			{
				MakeRoomResult recvData;
				bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize);
				assert(ret && recvData.mPlayerId == mLoginId);

				auto layer = cocos2d::Director::getInstance()->getRunningScene()->getChildByName("NetworkScene");
				if (layer == nullptr)
					break;

				scheduler->performFunctionInCocosThread(CC_CALLBACK_0(NetworkScene::MakeRoomComplete, dynamic_cast<NetworkScene*>(layer), recvData.mRoomId));
			}
			break;
		case PKT_SC_INOUT_ROOM:
			{
				InOutRoomResult recvData;
				bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize);
				assert(ret && recvData.mPlayerId == mLoginId);

				if (recvData.mIsIn)
				{
					auto layer = cocos2d::Director::getInstance()->getRunningScene()->getChildByName("NetworkScene");
					if (layer == nullptr)
						break;

					scheduler->performFunctionInCocosThread(CC_CALLBACK_0(NetworkScene::JoinRoomComplete, dynamic_cast<NetworkScene*>(layer), recvData.mRoomId));
				}
				else
				{
					// ÷̾ ó ʿ
// 					auto layer = cocos2d::Director::getInstance()->getRunningScene()->getChildByName("RoomScene");
// 					if (layer == nullptr)
// 						break;
//					scheduler->performFunctionInCocosThread(CC_CALLBACK_0(NetworkScene::MakeRoomComplete, dynamic_cast<NetworkScene*>(layer), recvData.mRoomId));
				}
			}
			break;

		case PKT_SC_ALL_READY:
		{
				GameRunNotify recvData;
				bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize);
				assert(ret && recvData.mPlayerId != -1);

				auto layer = cocos2d::Director::getInstance()->getRunningScene()->getChildByName("RoomScene");
				if (layer == nullptr)
					break;

				scheduler->performFunctionInCocosThread(CC_CALLBACK_0(RoomScene::GameStartComplete, dynamic_cast<RoomScene*>(layer)));
				return; //callbackԼ  ߰
		}
			break;

		case PKT_SC_CREATE_HERO:
			{
				CreateHeroResult recvData;
				bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize);
				assert(ret && recvData.mPlayerId != -1);

				auto layer = cocos2d::Director::getInstance()->getRunningScene()->getChildByName("MultiGameScene")->getChildByName("ListenerLayer")->getChildByName("ObjectLayer");
				if (layer == nullptr)
					break;

				Point pos = { recvData.mPosX, recvData.mPosY };
				scheduler->performFunctionInCocosThread(CC_CALLBACK_0(ObjectLayer::FirstDrawUnit, dynamic_cast<ObjectLayer*>(layer), recvData.mPlayerId, recvData.mUnitId, recvData.mUnitType, pos));
			}
			break;

		case PKT_SC_RUN_COMPLETE:
			{
				ServerRunCompleteNotify recvData;
				bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize);
				assert(ret && recvData.mPlayerId != -1);

				auto layer = cocos2d::Director::getInstance()->getRunningScene()->getChildByName("MultiGameScene")->getChildByName("LoadingBGLayer");
				if (layer == nullptr)
					break;

				scheduler->performFunctionInCocosThread(CC_CALLBACK_0(LoadingBGLayer::SetLoadingFin, dynamic_cast<LoadingBGLayer*>(layer)));
				return;
			}
			break;

		case PKT_SC_START_GAME:
			{
				StartGameNotify recvData;
				bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize);
				assert(ret && recvData.mPlayerId != -1);

				auto layer = cocos2d::Director::getInstance()->getRunningScene()->getChildByName("MultiGameScene");
				if (layer == nullptr)
					break;

				scheduler->performFunctionInCocosThread(CC_CALLBACK_0(MultiGameScene::StartGame, dynamic_cast<MultiGameScene*>(layer)));
			}
			break;

		case PKT_SC_MOVE:
			{
				MoveBroadcastResult recvData;
				bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize);
				assert(ret && recvData.mPlayerId != -1);

				auto layer = cocos2d::Director::getInstance()->getRunningScene()->getChildByName("MultiGameScene")->getChildByName("ListenerLayer")->getChildByName("ObjectLayer");
				if (layer == nullptr)
					break;

				Point curPos = { recvData.mCurrentPosX, recvData.mCurrentPosY };
				Point targetPos = { recvData.mTargetPosX, recvData.mTargetPosY };
				scheduler->performFunctionInCocosThread(CC_CALLBACK_0(ObjectLayer::UnitMove, dynamic_cast<ObjectLayer*>(layer), recvData.mUnitId, curPos, targetPos));
			}
			break;

		default:
			assert(false);
		}

	}
}

///////////////////////////////////////////////////////////////////////////
/*
	 Ŷ Ľϴ Լ
*/
///////////////////////////////////////////////////////////////////////////
void TcpClient::loginRequest()
{
	if (mLoginId > 0)
		return;

	srand(time(NULL));

	LoginRequest sendData;
	sendData.mPlayerId = 1000 + rand() % 101;

	send((const char*)&sendData, sizeof(LoginRequest));
}

void TcpClient::makeRoomRequest()
{
	if (mLoginId < 0)
		return;

	MakeRoomRequest sendData;
	sendData.mPlayerId = mLoginId;

	send((const char*)&sendData, sizeof(MakeRoomRequest));
}

void TcpClient::joinRoomRequest()
{
	if (mLoginId < 0)
		return;

	InOutRoomRequest sendData;
	sendData.mPlayerId = mLoginId;
	sendData.mIsIn = true;

	send((const char*)&sendData, sizeof(InOutRoomRequest));
}

void TcpClient::outRoomRequest(int roomId)
{
	if (mLoginId < 0)
		return;

	InOutRoomRequest sendData;
	sendData.mPlayerId = mLoginId;
	sendData.mIsIn = false;
	sendData.mRoomId = roomId;

	send((const char*)&sendData, sizeof(InOutRoomRequest));
}

void TcpClient::startGameRequest()
{
	if (mLoginId < 0)
		return;

	GameReadyNotify sendData;
	sendData.mPlayerId = mLoginId;

	send((const char*)&sendData, sizeof(GameReadyNotify));
}

void TcpClient::meReadyRequest()
{
	if (mLoginId < 0)
		return;

	ClientRunCompleteNotify sendData;
	sendData.mPlayerId = mLoginId;

	send((const char*)&sendData, sizeof(ClientRunCompleteNotify));
}

void TcpClient::moveRequest(Point curPos, Point targetPos)
{
	if (mLoginId < 0)
		return;

	MoveRequest sendData;
	sendData.mPlayerId = mLoginId;
	sendData.mCurrentPosX = curPos.x;
	sendData.mCurrentPosY = curPos.y;
	sendData.mTargetPosX = targetPos.x;
	sendData.mTargetPosY = targetPos.y;

	send((const char*)&sendData, sizeof(MoveRequest));
}

//  void TcpClient::chatRequest(const char* chat)
//  {
// 	 if (mLoginId < 0)
// 		 return;
//
// 	 ChatBroadcastRequest sendData;
//
// 	 sendData.mPlayerId = mLoginId;
// 	 memcpy(sendData.mChat, chat, strlen(chat));
//
// 	 send((const char*)&sendData, sizeof(ChatBroadcastRequest));
//  }
//
<commit_msg>[C] 패킷받기 하나추가<commit_after>#include <thread>
#include "TcpClient.h"
#include "platform/CCFileUtils.h"
#include "base/CCDirector.h"
#include "base/CCScheduler.h"
#include "2d/CCLabel.h"
#include "../../PacketType.h"
#include "SingleGameScene.h"
#include "ObjectLayer.h"
#include "NetworkScene.h"
#include "LoadingBGLayer.h"
#include "RoomScene.h"
#include "MultiGameScene.h"

#ifdef _WIN32
#pragma comment(lib,"ws2_32.lib")
#define sleep(x) Sleep(x)
#endif

static TcpClient* s_TcpClient = nullptr;

TcpClient::TcpClient() : mRecvBuffer(BUF_SIZE), mSock(NULL), mLoginId(-1)
{
	///
	auto t = std::thread(CC_CALLBACK_0(TcpClient::networkThread, this));
	t.detach();
}

TcpClient::~TcpClient()
{
	if(mSock == NULL)
		return;

#ifndef _WIN32
	close(mSock);
#else
	closesocket(mSock);
	WSACleanup();
#endif
}

TcpClient* TcpClient::getInstance()
{
	if (nullptr == s_TcpClient)
	{
		s_TcpClient = new TcpClient();
	}
	return s_TcpClient;
}

void TcpClient::destroyInstance()
{
	CC_SAFE_DELETE(s_TcpClient);
}

///////////////////////////////////////////////////////////////////////////
/*
	 ,  Լ
*/
///////////////////////////////////////////////////////////////////////////
bool TcpClient::connect()
{
	if (mSock != NULL)
	{
		TcpClient::getInstance()->disconnect();
	}

#ifdef _WIN32
	WSADATA wsa;
	if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
		return false;
#endif

	mSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (mSock == INVALID_SOCKET)
		return false;

	std::string ipaddr = cocos2d::UserDefault::getInstance()->getStringForKey("ipaddr", std::string("localhost"));
	int port = cocos2d::UserDefault::getInstance()->getIntegerForKey("port", 9001);

	struct hostent* host;
	struct sockaddr_in hostAddr;

	if ((host = gethostbyname(ipaddr.c_str())) == 0)
		return false;

	memset(&hostAddr, 0, sizeof(hostAddr));
	hostAddr.sin_family = AF_INET;
	hostAddr.sin_addr.s_addr = inet_addr("10.73.38.181");
	hostAddr.sin_port = htons(port);

	if (SOCKET_ERROR == ::connect(mSock, (struct sockaddr*)&hostAddr, sizeof(hostAddr)))
	{
		CCLOG("CONNECT FAILED");
		return false;
	}

	/// nagle ˰
	int opt = 1;
	setsockopt(mSock, IPPROTO_TCP, TCP_NODELAY, (const char*)&opt, sizeof(int));

	return true;
}

void TcpClient::disconnect()
{
	if (mSock == NULL)
		return;

#ifndef _WIN32
	close(mSock);
#else
	closesocket(mSock);
	WSACleanup();
#endif
	mSock = NULL;
	mLoginId = -1;

	return;
}

///////////////////////////////////////////////////////////////////////////
/*
	 Ŷ , ޴ Լ
*/
///////////////////////////////////////////////////////////////////////////
bool TcpClient::send(const char* data, int length)
{
	int count = 0;
	while (count < length)
	{
		int n = ::send(mSock, data + count, length, 0);
		if (n == SOCKET_ERROR)
		{
			CCLOG("SEND ERROR");
			return false;
		}
		count += n;
		length -= n;
	}

	return true;
}

void TcpClient::networkThread()
{
	while ( true )
	{
		char inBuf[4096] = { 0, };

		int n = ::recv(mSock, inBuf, 4096, 0);

		if (n < 1)
		{
			sleep(0); ///< for cpu low-utilization
			continue;
		}

		if (!mRecvBuffer.Write(inBuf, n))
		{
			///  á.
			assert(false);
		}

		processPacket();
	}
}

///////////////////////////////////////////////////////////////////////////
/*
	 Ŷ ĽϿ óϴ Լ
*/
///////////////////////////////////////////////////////////////////////////
void TcpClient::processPacket()
{
	auto scheduler = cocos2d::Director::getInstance()->getScheduler();

	/// Ŷ Ľؼ ϼǴ Ŷ , ش ݹ ҷش.
	while (true)
	{
		PacketHeader header;

		if (false == mRecvBuffer.Peek((char*)&header, sizeof(PacketHeader)))
			break;

		if (header.mSize > mRecvBuffer.GetStoredSize())
			break;

		switch (header.mType)
		{
		case PKT_SC_LOGIN:
			{
				LoginResult recvData;
				bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize);
				assert(ret && recvData.mPlayerId != -1);

				mLoginId = recvData.mPlayerId;

				auto layer = cocos2d::Director::getInstance()->getRunningScene()->getChildByName("NetworkScene");
				if (layer == nullptr)
					break;

				scheduler->performFunctionInCocosThread(CC_CALLBACK_0(NetworkScene::ConnectComplete, dynamic_cast<NetworkScene*>(layer)));
			}
			break;
		case PKT_SC_MAKE_ROOM:
			{
				MakeRoomResult recvData;
				bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize);
				assert(ret && recvData.mPlayerId == mLoginId);

				auto layer = cocos2d::Director::getInstance()->getRunningScene()->getChildByName("NetworkScene");
				if (layer == nullptr)
					break;

				scheduler->performFunctionInCocosThread(CC_CALLBACK_0(NetworkScene::MakeRoomComplete, dynamic_cast<NetworkScene*>(layer), recvData.mRoomId));
			}
			break;
		case PKT_SC_INOUT_ROOM:
			{
				InOutRoomResult recvData;
				bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize);
				assert(ret && recvData.mPlayerId == mLoginId);

				if (recvData.mIsIn)
				{
					auto layer = cocos2d::Director::getInstance()->getRunningScene()->getChildByName("NetworkScene");
					if (layer == nullptr)
						break;

					scheduler->performFunctionInCocosThread(CC_CALLBACK_0(NetworkScene::JoinRoomComplete, dynamic_cast<NetworkScene*>(layer), recvData.mRoomId));
				}
				else
				{
					// ÷̾ ó ʿ
// 					auto layer = cocos2d::Director::getInstance()->getRunningScene()->getChildByName("RoomScene");
// 					if (layer == nullptr)
// 						break;
//					scheduler->performFunctionInCocosThread(CC_CALLBACK_0(NetworkScene::MakeRoomComplete, dynamic_cast<NetworkScene*>(layer), recvData.mRoomId));
				}
			}
			break;

		case PKT_SC_ALL_READY:
		{
				GameRunNotify recvData;
				bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize);
				assert(ret && recvData.mPlayerId != -1);

				auto layer = cocos2d::Director::getInstance()->getRunningScene()->getChildByName("RoomScene");
				if (layer == nullptr)
					break;

				scheduler->performFunctionInCocosThread(CC_CALLBACK_0(RoomScene::GameStartComplete, dynamic_cast<RoomScene*>(layer)));
				return; //callbackԼ  ߰
		}
			break;

		case PKT_SC_CREATE_HERO:
			{
				CreateHeroResult recvData;
				bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize);
				assert(ret && recvData.mPlayerId != -1);

				auto layer = cocos2d::Director::getInstance()->getRunningScene()->getChildByName("MultiGameScene")->getChildByName("ListenerLayer")->getChildByName("ObjectLayer");
				if (layer == nullptr)
					break;

				Point pos = { recvData.mPosX, recvData.mPosY };
				scheduler->performFunctionInCocosThread(CC_CALLBACK_0(ObjectLayer::FirstDrawUnit, dynamic_cast<ObjectLayer*>(layer), recvData.mPlayerId, recvData.mUnitId, recvData.mUnitType, pos));
			}
			break;

		case PKT_SC_RUN_COMPLETE:
			{
				ServerRunCompleteNotify recvData;
				bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize);
				assert(ret && recvData.mPlayerId != -1);

				auto layer = cocos2d::Director::getInstance()->getRunningScene()->getChildByName("MultiGameScene")->getChildByName("LoadingBGLayer");
				if (layer == nullptr)
					break;

				scheduler->performFunctionInCocosThread(CC_CALLBACK_0(LoadingBGLayer::SetLoadingFin, dynamic_cast<LoadingBGLayer*>(layer)));
				return;
			}
			break;

		case PKT_SC_START_GAME:
			{
				StartGameNotify recvData;
				bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize);
				assert(ret && recvData.mPlayerId != -1);

				auto layer = cocos2d::Director::getInstance()->getRunningScene()->getChildByName("MultiGameScene");
				if (layer == nullptr)
					break;

				scheduler->performFunctionInCocosThread(CC_CALLBACK_0(MultiGameScene::StartGame, dynamic_cast<MultiGameScene*>(layer)));
			}
			break;

		case PKT_SC_MOVE:
			{
				MoveBroadcastResult recvData;
				bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize);
				assert(ret && recvData.mPlayerId != -1);

				auto layer = cocos2d::Director::getInstance()->getRunningScene()->getChildByName("MultiGameScene")->getChildByName("ListenerLayer")->getChildByName("ObjectLayer");
				if (layer == nullptr)
					break;

				Point curPos = { recvData.mCurrentPosX, recvData.mCurrentPosY };
				Point targetPos = { recvData.mTargetPosX, recvData.mTargetPosY };
				scheduler->performFunctionInCocosThread(CC_CALLBACK_0(ObjectLayer::UnitMove, dynamic_cast<ObjectLayer*>(layer), recvData.mUnitId, curPos, targetPos));
			}
			break;

		case PKT_SC_CRASH:
			{
				CrashedBroadcastResult recvData;
				bool ret = mRecvBuffer.Read((char*)&recvData, recvData.mSize);
				assert(ret && recvData.mPlayerId != -1);

				auto layer = cocos2d::Director::getInstance()->getRunningScene()->getChildByName("MultiGameScene")->getChildByName("ListenerLayer")->getChildByName("ObjectLayer");
				if (layer == nullptr)
					break;

				Point curPos = { recvData.mCurrentPosX, recvData.mCurrentPosY };
				scheduler->performFunctionInCocosThread(CC_CALLBACK_0(ObjectLayer::UnitCrash, dynamic_cast<ObjectLayer*>(layer), recvData.mUnitId, curPos));
				if (!recvData.mIsCrashed)
					scheduler->performFunctionInCocosThread(CC_CALLBACK_0(ObjectLayer::UnitCrashEnd, dynamic_cast<ObjectLayer*>(layer), recvData.mUnitId));
			}
			break;

		default:
			assert(false);
		}

	}
}

///////////////////////////////////////////////////////////////////////////
/*
	 Ŷ Ľϴ Լ
*/
///////////////////////////////////////////////////////////////////////////
void TcpClient::loginRequest()
{
	if (mLoginId > 0)
		return;

	srand(time(NULL));

	LoginRequest sendData;
	sendData.mPlayerId = 1000 + rand() % 101;

	send((const char*)&sendData, sizeof(LoginRequest));
}

void TcpClient::makeRoomRequest()
{
	if (mLoginId < 0)
		return;

	MakeRoomRequest sendData;
	sendData.mPlayerId = mLoginId;

	send((const char*)&sendData, sizeof(MakeRoomRequest));
}

void TcpClient::joinRoomRequest()
{
	if (mLoginId < 0)
		return;

	InOutRoomRequest sendData;
	sendData.mPlayerId = mLoginId;
	sendData.mIsIn = true;

	send((const char*)&sendData, sizeof(InOutRoomRequest));
}

void TcpClient::outRoomRequest(int roomId)
{
	if (mLoginId < 0)
		return;

	InOutRoomRequest sendData;
	sendData.mPlayerId = mLoginId;
	sendData.mIsIn = false;
	sendData.mRoomId = roomId;

	send((const char*)&sendData, sizeof(InOutRoomRequest));
}

void TcpClient::startGameRequest()
{
	if (mLoginId < 0)
		return;

	GameReadyNotify sendData;
	sendData.mPlayerId = mLoginId;

	send((const char*)&sendData, sizeof(GameReadyNotify));
}

void TcpClient::meReadyRequest()
{
	if (mLoginId < 0)
		return;

	ClientRunCompleteNotify sendData;
	sendData.mPlayerId = mLoginId;

	send((const char*)&sendData, sizeof(ClientRunCompleteNotify));
}

void TcpClient::moveRequest(Point curPos, Point targetPos)
{
	if (mLoginId < 0)
		return;

	MoveRequest sendData;
	sendData.mPlayerId = mLoginId;
	sendData.mCurrentPosX = curPos.x;
	sendData.mCurrentPosY = curPos.y;
	sendData.mTargetPosX = targetPos.x;
	sendData.mTargetPosY = targetPos.y;

	send((const char*)&sendData, sizeof(MoveRequest));
}

//  void TcpClient::chatRequest(const char* chat)
//  {
// 	 if (mLoginId < 0)
// 		 return;
//
// 	 ChatBroadcastRequest sendData;
//
// 	 sendData.mPlayerId = mLoginId;
// 	 memcpy(sendData.mChat, chat, strlen(chat));
//
// 	 send((const char*)&sendData, sizeof(ChatBroadcastRequest));
//  }
//
<|endoftext|>