<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2018.  All rights reserved
 */
#ifndef _Stroika_Foundation_Streams_LoggingInputOutputStream_inl_
#define _Stroika_Foundation_Streams_LoggingInputOutputStream_inl_ 1

/*
********************************************************************************
***************************** Implementation Details ***************************
********************************************************************************
*/

namespace Stroika {
    namespace Foundation {
        namespace Streams {

            /*
             ********************************************************************************
             **************** Streams::LoggingInputOutputStream::Rep_ ***********************
             ********************************************************************************
             */
            template <typename ELEMENT_TYPE>
            class LoggingInputOutputStream<ELEMENT_TYPE>::Rep_ : public InputOutputStream<ELEMENT_TYPE>::_IRep, private Debug::AssertExternallySynchronizedLock {
            public:
                Rep_ (const typename InputOutputStream<ELEMENT_TYPE>::Ptr& realStream, const typename OutputStream<ELEMENT_TYPE>::Ptr& logInput, const typename OutputStream<ELEMENT_TYPE>::Ptr& logOutput)
                    : InputOutputStream<ELEMENT_TYPE>::_IRep ()
                    , fRealStream_ (realStream)
                    , fLogInput_ (logInput)
                    , fLogOutput_ (logOutput)
                {
                }

                // Stream<ELEMENT_TYPE>::_IRep
            public:
                virtual bool IsSeekable () const override
                {
                    return fRealOut1_.IsSeekable ();
                }

                // InputStream::_IRep
            public:
                virtual void CloseRead () override
                {
                    fRealStream_.CloseRead ();
                    fLogInput_.Close ();
                }
                virtual bool IsOpenRead () const override
                {
                    return fRealStream_.IsOpenRead ();
                }
                virtual SeekOffsetType GetReadOffset () const override
                {
                    return fRealStream_.GetReadOffset ();
                }
                virtual SeekOffsetType SeekRead (Whence whence, SignedSeekOffsetType offset) override
                {
                    SeekOffsetType result = fRealStream_.SeekRead (whence, offset);
                    // @todo - perhaps should seek the fLogInput_ stream? But not clear by how much
                    return result;
                }
                virtual size_t Read (ElementType* intoStart, ElementType* intoEnd) override
                {
                    size_t result = fRealStream_.Read (intoStart, intoEnd);
                    fLogInput_.Write (intoStart, intoStart + result);
                    return result;
                }
                virtual Memory::Optional<size_t> ReadNonBlocking (ElementType* intoStart, ElementType* intoEnd) override
                {
                    size_t result = fRealStream_.ReadNonBlocking (intoStart, intoEnd);
                    fLogInput_.Write (intoStart, intoStart + result);
                    return result;
                }

                // OutputStream::_IRep
            public:
                virtual void CloseWrite () override
                {
                    Require (IsOpenWrite ());
                    fRealStream_.CloseWrite ();
                    Assert (fRealStream_ == nullptr);
                }
                virtual bool IsOpenWrite () const override
                {
                    return fRealStream_.IsOpenWrite ();
                }
                virtual SeekOffsetType GetWriteOffset () const override
                {
                    return fRealStream_.GetWriteOffset ();
                }
                virtual SeekOffsetType SeekWrite (Whence whence, SignedSeekOffsetType offset) override
                {
                    Require (IsOpenWrite ());
                    SeekOffsetType o1 = fRealStream_.SeekWrite (whence, offset);
                    SeekOffsetType o2 = fLogOutput_.SeekWrite (whence, offset); // @todo - not sure if/how mcuh to see - since not totally in sync
                    return o1;
                }
                virtual void Flush () override
                {
                    lock_guard<const AssertExternallySynchronizedLock> critSec{*this};
                    Require (IsOpenWrite ());
                    fRealStream_.Flush ();
                }
                // pointer must refer to valid memory at least bufSize long, and cannot be nullptr. BufSize must always be >= 1.
                // Writes always succeed fully or throw.
                virtual void Write (const ELEMENT_TYPE* start, const ELEMENT_TYPE* end) override
                {
                    Require (start < end); // for OutputStream<Byte> - this funciton requires non-empty write
                    Require (IsOpenWrite ());
                    lock_guard<const AssertExternallySynchronizedLock> critSec{*this};
                    fRealStream_.Write (start, end);
                    fLogOutput_.Write (start, end);
                }

            private:
                typename InputOutputStream<ELEMENT_TYPE>::Ptr fRealStream_;
                typename OutputStream<ELEMENT_TYPE>::Ptr      fLogInput_;
                typename OutputStream<ELEMENT_TYPE>::Ptr      fLogOutput_;
            };

            /*
             ********************************************************************************
             **************** Streams::LoggingInputOutputStream::Rep_ ***********************
             ********************************************************************************
             */
            template <typename ELEMENT_TYPE>
            typename LoggingInputOutputStream<ELEMENT_TYPE>::Ptr LoggingInputOutputStream<ELEMENT_TYPE>::New (const typename InputOutputStream<ELEMENT_TYPE>::Ptr& realStream, const typename OutputStream<ELEMENT_TYPE>::Ptr& logInput, const typename OutputStream<ELEMENT_TYPE>::Ptr& logOutput)
            {
                return make_shared<Rep_> (realStream, logInput, logOutput);
            }
            template <typename ELEMENT_TYPE>
            typename LoggingInputOutputStream<ELEMENT_TYPE>::Ptr LoggingInputOutputStream<ELEMENT_TYPE>::New (Execution::InternallySyncrhonized internallySyncrhonized, const typename InputOutputStream<ELEMENT_TYPE>::Ptr& realStream, const typename OutputStream<ELEMENT_TYPE>::Ptr& logInput, const typename OutputStream<ELEMENT_TYPE>::Ptr& logOutput)
            {
                switch (internallySyncrhonized) {
                    case Execution::eInternallySynchronized:
                        return InternalSyncRep_::New (realStream, logInput, logOutput);
                    case Execution::eNotKnownInternallySynchronized:
                        return New (realStream, logInput, logOutput);
                    default:
                        RequireNotReached ();
                        return nullptr;
                }
            }
        }
    }
}
#endif /*_Stroika_Foundation_Streams_LoggingInputOutputStream_inl_*/
<commit_msg>fixes to new Streams/LoggingInputOutputStream<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2018.  All rights reserved
 */
#ifndef _Stroika_Foundation_Streams_LoggingInputOutputStream_inl_
#define _Stroika_Foundation_Streams_LoggingInputOutputStream_inl_ 1

/*
********************************************************************************
***************************** Implementation Details ***************************
********************************************************************************
*/

namespace Stroika {
    namespace Foundation {
        namespace Streams {

            /*
             ********************************************************************************
             **************** Streams::LoggingInputOutputStream::Rep_ ***********************
             ********************************************************************************
             */
            template <typename ELEMENT_TYPE>
            class LoggingInputOutputStream<ELEMENT_TYPE>::Rep_ : public InputOutputStream<ELEMENT_TYPE>::_IRep, private Debug::AssertExternallySynchronizedLock {
            public:
                Rep_ (const typename InputOutputStream<ELEMENT_TYPE>::Ptr& realStream, const typename OutputStream<ELEMENT_TYPE>::Ptr& logInput, const typename OutputStream<ELEMENT_TYPE>::Ptr& logOutput)
                    : InputOutputStream<ELEMENT_TYPE>::_IRep ()
                    , fRealStream_ (realStream)
                    , fLogInput_ (logInput)
                    , fLogOutput_ (logOutput)
                {
                    Require (not realStream.IsSeekable () or (logInput.IsSeekable () and logOutput.IsSeekable ())); // since may need to delegate seeks
                }

                // Stream<ELEMENT_TYPE>::_IRep
            public:
                virtual bool IsSeekable () const override
                {
                    return fRealStream_.IsSeekable ();
                }

                // InputStream::_IRep
            public:
                virtual void CloseRead () override
                {
                    fRealStream_.CloseRead ();
                    fLogInput_.Close ();
                }
                virtual bool IsOpenRead () const override
                {
                    return fRealStream_.IsOpenRead ();
                }
                virtual SeekOffsetType GetReadOffset () const override
                {
                    return fRealStream_.GetReadOffset ();
                }
                virtual SeekOffsetType SeekRead (Whence whence, SignedSeekOffsetType offset) override
                {
                    SeekOffsetType result = fRealStream_.SeekRead (whence, offset);
                    // @todo - perhaps should seek the fLogInput_ stream? But not clear by how much
                    return result;
                }
                virtual size_t Read (ElementType* intoStart, ElementType* intoEnd) override
                {
                    size_t result = fRealStream_.Read (intoStart, intoEnd);
                    fLogInput_.Write (intoStart, intoStart + result);
                    return result;
                }
                virtual Memory::Optional<size_t> ReadNonBlocking (ElementType* intoStart, ElementType* intoEnd) override
                {
                    Memory::Optional<size_t> result = fRealStream_.ReadNonBlocking (intoStart, intoEnd);
                    if (result) {
                        fLogInput_.Write (intoStart, intoStart + *result);
                    }
                    return result;
                }

                // OutputStream::_IRep
            public:
                virtual void CloseWrite () override
                {
                    Require (IsOpenWrite ());
                    fRealStream_.CloseWrite ();
                    Assert (fRealStream_ == nullptr);
                }
                virtual bool IsOpenWrite () const override
                {
                    return fRealStream_.IsOpenWrite ();
                }
                virtual SeekOffsetType GetWriteOffset () const override
                {
                    return fRealStream_.GetWriteOffset ();
                }
                virtual SeekOffsetType SeekWrite (Whence whence, SignedSeekOffsetType offset) override
                {
                    Require (IsOpenWrite ());
                    SeekOffsetType o1 = fRealStream_.SeekWrite (whence, offset);
                    SeekOffsetType o2 = fLogOutput_.Seek (whence, offset); // @todo - not sure if/how mcuh to see - since not totally in sync
                    return o1;
                }
                virtual void Flush () override
                {
                    lock_guard<const AssertExternallySynchronizedLock> critSec{*this};
                    Require (IsOpenWrite ());
                    fRealStream_.Flush ();
                }
                // pointer must refer to valid memory at least bufSize long, and cannot be nullptr. BufSize must always be >= 1.
                // Writes always succeed fully or throw.
                virtual void Write (const ELEMENT_TYPE* start, const ELEMENT_TYPE* end) override
                {
                    Require (start < end); // for OutputStream<Byte> - this funciton requires non-empty write
                    Require (IsOpenWrite ());
                    lock_guard<const AssertExternallySynchronizedLock> critSec{*this};
                    fRealStream_.Write (start, end);
                    fLogOutput_.Write (start, end);
                }

            private:
                typename InputOutputStream<ELEMENT_TYPE>::Ptr fRealStream_;
                typename OutputStream<ELEMENT_TYPE>::Ptr      fLogInput_;
                typename OutputStream<ELEMENT_TYPE>::Ptr      fLogOutput_;
            };

            /*
             ********************************************************************************
             **************** Streams::LoggingInputOutputStream::Rep_ ***********************
             ********************************************************************************
             */
            template <typename ELEMENT_TYPE>
            typename LoggingInputOutputStream<ELEMENT_TYPE>::Ptr LoggingInputOutputStream<ELEMENT_TYPE>::New (const typename InputOutputStream<ELEMENT_TYPE>::Ptr& realStream, const typename OutputStream<ELEMENT_TYPE>::Ptr& logInput, const typename OutputStream<ELEMENT_TYPE>::Ptr& logOutput)
            {
                return make_shared<Rep_> (realStream, logInput, logOutput);
            }
            template <typename ELEMENT_TYPE>
            typename LoggingInputOutputStream<ELEMENT_TYPE>::Ptr LoggingInputOutputStream<ELEMENT_TYPE>::New (Execution::InternallySyncrhonized internallySyncrhonized, const typename InputOutputStream<ELEMENT_TYPE>::Ptr& realStream, const typename OutputStream<ELEMENT_TYPE>::Ptr& logInput, const typename OutputStream<ELEMENT_TYPE>::Ptr& logOutput)
            {
                switch (internallySyncrhonized) {
                    case Execution::eInternallySynchronized:
                        return InternalSyncRep_::New (realStream, logInput, logOutput);
                    case Execution::eNotKnownInternallySynchronized:
                        return New (realStream, logInput, logOutput);
                    default:
                        RequireNotReached ();
                        return nullptr;
                }
            }
        }
    }
}
#endif /*_Stroika_Foundation_Streams_LoggingInputOutputStream_inl_*/
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2015.  All rights reserved
 */
#include    "../../StroikaPreComp.h"

#if     qPlatform_Windows
#include    <Windows.h>
#endif

#include    "../../../Foundation/Characters/String_Constant.h"
#include    "../../../Foundation/Characters/String2Float.h"
#include    "../../../Foundation/DataExchange/CharacterDelimitedLines/Reader.h"
#include    "../../../Foundation/Debug/Assertions.h"
#include    "../../../Foundation/Execution/Sleep.h"
#include    "../../../Foundation/IO/FileSystem/BinaryFileInputStream.h"
#include    "../../../Foundation/Math/Common.h"

#include    "CPU.h"

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Containers;
using   namespace   Stroika::Foundation::DataExchange;
using   namespace   Stroika::Foundation::Memory;

using   namespace   Stroika::Frameworks;
using   namespace   Stroika::Frameworks::SystemPerformance;
using   namespace   Stroika::Frameworks::SystemPerformance::Instruments::CPU;

using   Characters::String_Constant;
using   Time::DurationSecondsType;

// Comment this in to turn on aggressive noisy DbgTrace in this module
//#define   USE_NOISY_TRACE_IN_THIS_MODULE_       1

#if     qSupport_SystemPerformance_Instruments_CPU_LoadAverage
/*
 ********************************************************************************
 *********************** Instruments::CPU::Info::LoadAverage ********************
 ********************************************************************************
 */
Instruments::CPU::Info::LoadAverage::LoadAverage (double oneMinuteAve, double fiveMinuteAve, double fifteenMinuteAve)
    : f1MinuteAve (oneMinuteAve)
    , f5MinuteAve (fiveMinuteAve)
    , f15MinuteAve (fifteenMinuteAve)
{
}
#endif

/*
 ********************************************************************************
 ***************** Instruments::CPU::GetObjectVariantMapper *********************
 ********************************************************************************
 */
ObjectVariantMapper Instruments::CPU::GetObjectVariantMapper ()
{
    using   StructureFieldInfo = ObjectVariantMapper::StructureFieldInfo;
    ObjectVariantMapper sMapper_ = [] () -> ObjectVariantMapper {
        ObjectVariantMapper mapper;
        DISABLE_COMPILER_CLANG_WARNING_START("clang diagnostic ignored \"-Winvalid-offsetof\"");   // Really probably an issue, but not to debug here -- LGP 2014-01-04
        DISABLE_COMPILER_GCC_WARNING_START("GCC diagnostic ignored \"-Winvalid-offsetof\"");       // Really probably an issue, but not to debug here -- LGP 2014-01-04
#if     qSupport_SystemPerformance_Instruments_CPU_LoadAverage
        mapper.AddClass<Info::LoadAverage> (initializer_list<StructureFieldInfo> {
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (Info::LoadAverage, f1MinuteAve), String_Constant (L"1-minute") },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (Info::LoadAverage, f5MinuteAve), String_Constant (L"5-minute") },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (Info::LoadAverage, f15MinuteAve), String_Constant (L"15-minute") },
        });
        mapper.AddCommonType<Optional_Indirect_Storage<Info::LoadAverage>> ();
#endif
        mapper.AddClass<Info> (initializer_list<StructureFieldInfo> {
#if     qSupport_SystemPerformance_Instruments_CPU_LoadAverage
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (Info, fLoadAverage), String_Constant (L"Load-Average"), StructureFieldInfo::NullFieldHandling::eOmit },
#endif
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (Info, fTotalCPUUsage), String_Constant (L"Total-CPU-Usage") },
        });
        DISABLE_COMPILER_GCC_WARNING_END("GCC diagnostic ignored \"-Winvalid-offsetof\"");
        DISABLE_COMPILER_CLANG_WARNING_END("clang diagnostic ignored \"-Winvalid-offsetof\"");
        return mapper;
    } ();
    return sMapper_;
}

namespace {
    struct  CapturerWithContext_COMMON_ {
        Options                     fOptions_;
        DurationSecondsType         fPostponeCaptureUntil_ { 0 };
        DateTime                    fLastCapturedAt;
        DurationSecondsType         fMinimumAveragingInterval_;
        CapturerWithContext_COMMON_ (const Options& options)
            : fOptions_ (options)
            , fMinimumAveragingInterval_ (options.fMinimumAveragingInterval)
        {
        }
        void    NoteCompletedCapture_ ()
        {
            fPostponeCaptureUntil_ = Time::GetTickCount () + fMinimumAveragingInterval_;
            fLastCapturedAt = DateTime::Now ();
        }
    };
}

#if     qPlatform_POSIX
namespace {
    struct  CapturerWithContext_POSIX_ : CapturerWithContext_COMMON_ {
        struct  POSIXSysTimeCaptureContext_ {
            double  user;
            //double  nice;
            double  system;
            double  idle;
        };
        POSIXSysTimeCaptureContext_     fContext_ {};
        CapturerWithContext_POSIX_ (const Options& options)
            : CapturerWithContext_COMMON_ (options)
        {
            capture_ ();    // Force fill of context - ignore results
        }
        /*
         *  /proc/stat
         *      EXAMPLE:
         *          lewis@LewisLinuxDevVM2:~$ cat /proc/stat
         *          cpu  361378 1170 50632 2812384 5609 3 2684 0 0 0
         *          cpu0 202907 894 27261 1382587 3014 3 2672 0 0 0
         *          cpu1 158471 276 23371 1429797 2595 0 12 0 0 0
         *
         *  From http://man7.org/linux/man-pages/man5/proc.5.html
         *
         *        kernel/system statistics.  Varies with architecture.  Common
         *         entries include:
         *
         *         cpu  3357 0 4313 1362393
         *                The amount of time, measured in units of USER_HZ
         *                (1/100ths of a second on most architectures, use
         *                sysconf(_SC_CLK_TCK) to obtain the right value), that
         *                the system spent in various states:
         *
         *                user   (1) Time spent in user mode.
         *
         *                nice   (2) Time spent in user mode with low priority
         *                       (nice).
         *
         *                system (3) Time spent in system mode.
         *
         *                idle   (4) Time spent in the idle task.  This value
         *                       should be USER_HZ times the second entry in the
         *                       /proc/uptime pseudo-file.
         */
        static  inline  POSIXSysTimeCaptureContext_    GetSysTimes_ ()
        {
            POSIXSysTimeCaptureContext_   result;
            using   IO::FileSystem::BinaryFileInputStream;
            using   Characters::String2Float;
            DataExchange::CharacterDelimitedLines::Reader reader {{' ', '\t' }};
            const   String_Constant kFileName_ { L"/proc/stat" };
            // Note - /procfs files always unseekable
            for (Sequence<String> line : reader.ReadMatrix (BinaryFileInputStream::mk (kFileName_, BinaryFileInputStream::eNotSeekable))) {
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
                DbgTrace (L"***in Instruments::CPU::capture_GetSysTimes_ linesize=%d, line[0]=%s", line.size(), line.empty () ? L"" : line[0].c_str ());
#endif
                if (line.size () >= 5 and line[0] == L"cpu") {
                    result.user = String2Float<double> (line[1]);
                    result.system = String2Float<double> (line[3]);
                    result.idle = String2Float<double> (line[4]);
                    break;  // once found no need to read the rest...
                }
            }
            return result;
        }
        double  cputime_ ()
        {
            POSIXSysTimeCaptureContext_   baseline = fContext_;
            POSIXSysTimeCaptureContext_   newVal = GetSysTimes_ ();
            fContext_ = newVal;

            double  usedSysTime = (newVal.user - baseline.user) + (newVal.system - baseline.system);
            double  totalTime = usedSysTime + (newVal.idle - baseline.idle);
            if (Math::NearlyEquals<double> (totalTime, 0)) {
                // can happen if called too quickly together. No good answer
                DbgTrace ("Warning - times too close together for cputime_");
                return 0;
            }
            Assert (totalTime > 0);
            double cpu =  usedSysTime * 100 / totalTime;
            return Math::PinInRange<double> (cpu, 0, 100);
        }
        Info capture_ ()
        {
            Execution::SleepUntil (fPostponeCaptureUntil_);
            Info    result;
#if     qSupport_SystemPerformance_Instruments_CPU_LoadAverage
            {
                double loadAve[3];
                int lr = ::getloadavg (loadAve, 3);
                if (lr == 3) {
                    result.fLoadAverage = Info::LoadAverage (loadAve[0], loadAve[1], loadAve[2]);
                }
                else {
                    DbgTrace ("getloadave failed - with result = %d", lr);
                }
            }
#endif
            result.fTotalCPUUsage = cputime_ ();
            NoteCompletedCapture_ ();
            return result;
        }
    };
}
#endif

#if   qPlatform_Windows
namespace {
    struct  CapturerWithContext_Windows_ : CapturerWithContext_COMMON_ {
        struct  WinSysTimeCaptureContext_ {
            double  IdleTime;
            double  KernelTime;
            double  UserTime;
        };
        WinSysTimeCaptureContext_   fContext_;
        CapturerWithContext_Windows_ (const Options& options)
            : CapturerWithContext_COMMON_ (options)
        {
            capture_ ();    // Force fill of context
        }
        static  inline  double  GetAsSeconds_ (FILETIME ft)
        {
            ULARGE_INTEGER  ui;
            ui.LowPart = ft.dwLowDateTime;
            ui.HighPart = ft.dwHighDateTime;
            // convert from 100-nanosecond units
            return static_cast<double> (ui.QuadPart) / 10000000;
        }
        static  inline  WinSysTimeCaptureContext_    GetSysTimes_ ()
        {
            FILETIME    curIdleTime_;
            FILETIME    curKernelTime_;
            FILETIME    curUserTime_;
            memset (&curIdleTime_, 0, sizeof (curIdleTime_));
            memset (&curKernelTime_, 0, sizeof (curKernelTime_));
            memset (&curUserTime_, 0, sizeof (curUserTime_));
            Verify (::GetSystemTimes (&curIdleTime_, &curKernelTime_, &curUserTime_));
            return WinSysTimeCaptureContext_ { GetAsSeconds_ (curIdleTime_), GetAsSeconds_ (curKernelTime_), GetAsSeconds_ (curUserTime_) };
        }
        double  cputime_ ()
        {
            WinSysTimeCaptureContext_   baseline = fContext_;
            WinSysTimeCaptureContext_   newVal = GetSysTimes_ ();
            fContext_ = newVal;

            double  idleTimeOverInterval = newVal.IdleTime - baseline.IdleTime;
            double  kernelTimeOverInterval = newVal.KernelTime - baseline.KernelTime;
            double  userTimeOverInterval = newVal.UserTime - baseline.UserTime;

            double sys = kernelTimeOverInterval + userTimeOverInterval;
            Assert (sys > 0);
            double cpu =  (sys - idleTimeOverInterval) * 100 / sys;
            return Math::PinInRange<double> (cpu, 0, 100);
        }
        Info capture_ ()
        {
            Info    result;
            Execution::SleepUntil (fPostponeCaptureUntil_);
            result.fTotalCPUUsage = cputime_ ();
            NoteCompletedCapture_ ();
            return result;
        }
    };
}
#endif

namespace {
    struct  CapturerWithContext_
            : Debug::AssertExternallySynchronizedLock
#if     qPlatform_POSIX
            , CapturerWithContext_POSIX_
#elif   qPlatform_Windows
            , CapturerWithContext_Windows_
#endif
    {
#if     qPlatform_POSIX
        using inherited = CapturerWithContext_POSIX_;
#elif   qPlatform_Windows
        using inherited = CapturerWithContext_Windows_;
#endif
        CapturerWithContext_ (Options options)
            : inherited (options)
        {
        }
        Info capture_ ()
        {
            lock_guard<const AssertExternallySynchronizedLock> critSec { *this };
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
            Debug::TraceContextBumper ctx ("Instruments::CPU capture_");
#endif
            return inherited::capture_ ();
        }
    };
}

/*
 ********************************************************************************
 ************************* Instruments::CPU::GetInstrument **********************
 ********************************************************************************
 */
Instrument  SystemPerformance::Instruments::CPU::GetInstrument (Options options)
{
    CapturerWithContext_ useCaptureContext { options };  // capture context so copyable in mutable lambda
    static  const   MeasurementType kCPUMeasurment_         =   MeasurementType (String_Constant (L"CPU-Usage"));
    return Instrument (
               InstrumentNameType (String_Constant (L"CPU")),
    [useCaptureContext] () mutable -> MeasurementSet {
        MeasurementSet    results;
        DateTime    before = useCaptureContext.fLastCapturedAt;
        Info rawMeasurement = useCaptureContext.capture_ ();
        results.fMeasuredAt = DateTimeRange (before, useCaptureContext.fLastCapturedAt);
        Measurement m;
        m.fValue = GetObjectVariantMapper ().FromObject (rawMeasurement);
        m.fType = kCPUMeasurment_;
        results.fMeasurements.Add (m);
        return results;
    },
    {kCPUMeasurment_},
    GetObjectVariantMapper ()
           );
}
<commit_msg>Comments<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2015.  All rights reserved
 */
#include    "../../StroikaPreComp.h"

#if     qPlatform_Windows
#include    <Windows.h>
#endif

#include    "../../../Foundation/Characters/String_Constant.h"
#include    "../../../Foundation/Characters/String2Float.h"
#include    "../../../Foundation/DataExchange/CharacterDelimitedLines/Reader.h"
#include    "../../../Foundation/Debug/Assertions.h"
#include    "../../../Foundation/Execution/Sleep.h"
#include    "../../../Foundation/IO/FileSystem/BinaryFileInputStream.h"
#include    "../../../Foundation/Math/Common.h"

#include    "CPU.h"

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Containers;
using   namespace   Stroika::Foundation::DataExchange;
using   namespace   Stroika::Foundation::Memory;

using   namespace   Stroika::Frameworks;
using   namespace   Stroika::Frameworks::SystemPerformance;
using   namespace   Stroika::Frameworks::SystemPerformance::Instruments::CPU;

using   Characters::String_Constant;
using   Time::DurationSecondsType;

// Comment this in to turn on aggressive noisy DbgTrace in this module
//#define   USE_NOISY_TRACE_IN_THIS_MODULE_       1

#if     qSupport_SystemPerformance_Instruments_CPU_LoadAverage
/*
 ********************************************************************************
 *********************** Instruments::CPU::Info::LoadAverage ********************
 ********************************************************************************
 */
Instruments::CPU::Info::LoadAverage::LoadAverage (double oneMinuteAve, double fiveMinuteAve, double fifteenMinuteAve)
    : f1MinuteAve (oneMinuteAve)
    , f5MinuteAve (fiveMinuteAve)
    , f15MinuteAve (fifteenMinuteAve)
{
}
#endif

/*
 ********************************************************************************
 ***************** Instruments::CPU::GetObjectVariantMapper *********************
 ********************************************************************************
 */
ObjectVariantMapper Instruments::CPU::GetObjectVariantMapper ()
{
    using   StructureFieldInfo = ObjectVariantMapper::StructureFieldInfo;
    ObjectVariantMapper sMapper_ = [] () -> ObjectVariantMapper {
        ObjectVariantMapper mapper;
        DISABLE_COMPILER_CLANG_WARNING_START("clang diagnostic ignored \"-Winvalid-offsetof\"");   // Really probably an issue, but not to debug here -- LGP 2014-01-04
        DISABLE_COMPILER_GCC_WARNING_START("GCC diagnostic ignored \"-Winvalid-offsetof\"");       // Really probably an issue, but not to debug here -- LGP 2014-01-04
#if     qSupport_SystemPerformance_Instruments_CPU_LoadAverage
        mapper.AddClass<Info::LoadAverage> (initializer_list<StructureFieldInfo> {
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (Info::LoadAverage, f1MinuteAve), String_Constant (L"1-minute") },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (Info::LoadAverage, f5MinuteAve), String_Constant (L"5-minute") },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (Info::LoadAverage, f15MinuteAve), String_Constant (L"15-minute") },
        });
        mapper.AddCommonType<Optional_Indirect_Storage<Info::LoadAverage>> ();
#endif
        mapper.AddClass<Info> (initializer_list<StructureFieldInfo> {
#if     qSupport_SystemPerformance_Instruments_CPU_LoadAverage
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (Info, fLoadAverage), String_Constant (L"Load-Average"), StructureFieldInfo::NullFieldHandling::eOmit },
#endif
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (Info, fTotalCPUUsage), String_Constant (L"Total-CPU-Usage") },
        });
        DISABLE_COMPILER_GCC_WARNING_END("GCC diagnostic ignored \"-Winvalid-offsetof\"");
        DISABLE_COMPILER_CLANG_WARNING_END("clang diagnostic ignored \"-Winvalid-offsetof\"");
        return mapper;
    } ();
    return sMapper_;
}

namespace {
    struct  CapturerWithContext_COMMON_ {
        Options                     fOptions_;
        DurationSecondsType         fPostponeCaptureUntil_ { 0 };
        DateTime                    fLastCapturedAt;
        DurationSecondsType         fMinimumAveragingInterval_;
        CapturerWithContext_COMMON_ (const Options& options)
            : fOptions_ (options)
            , fMinimumAveragingInterval_ (options.fMinimumAveragingInterval)
        {
        }
        void    NoteCompletedCapture_ ()
        {
            fPostponeCaptureUntil_ = Time::GetTickCount () + fMinimumAveragingInterval_;
            fLastCapturedAt = DateTime::Now ();
        }
    };
}

#if     qPlatform_POSIX
namespace {
    struct  CapturerWithContext_POSIX_ : CapturerWithContext_COMMON_ {
        struct  POSIXSysTimeCaptureContext_ {
            double  user;
            //double  nice;
            double  system;
            double  idle;
        };
        POSIXSysTimeCaptureContext_     fContext_ {};
        CapturerWithContext_POSIX_ (const Options& options)
            : CapturerWithContext_COMMON_ (options)
        {
            capture_ ();    // Force fill of context - ignore results
        }
        /*
         *  /proc/stat
         *      EXAMPLE:
         *          lewis@LewisLinuxDevVM2:~$ cat /proc/stat
         *          cpu  361378 1170 50632 2812384 5609 3 2684 0 0 0
         *          cpu0 202907 894 27261 1382587 3014 3 2672 0 0 0
         *          cpu1 158471 276 23371 1429797 2595 0 12 0 0 0
         *
         *  From http://man7.org/linux/man-pages/man5/proc.5.html
         *
         *        kernel/system statistics.  Varies with architecture.  Common
         *         entries include:
         *
         *         cpu  3357 0 4313 1362393
         *                The amount of time, measured in units of USER_HZ
         *                (1/100ths of a second on most architectures, use
         *                sysconf(_SC_CLK_TCK) to obtain the right value), that
         *                the system spent in various states:
         *
         *                user   (1) Time spent in user mode.
         *
         *                nice   (2) Time spent in user mode with low priority
         *                       (nice).
         *
         *                system (3) Time spent in system mode.
         *
         *                idle   (4) Time spent in the idle task.  This value
         *                       should be USER_HZ times the second entry in the
         *                       /proc/uptime pseudo-file.
         */
        static  inline  POSIXSysTimeCaptureContext_    GetSysTimes_ ()
        {
            POSIXSysTimeCaptureContext_   result;
            using   IO::FileSystem::BinaryFileInputStream;
            using   Characters::String2Float;
            DataExchange::CharacterDelimitedLines::Reader reader {{' ', '\t' }};
            const   String_Constant kFileName_ { L"/proc/stat" };
            // Note - /procfs files always unseekable
            for (Sequence<String> line : reader.ReadMatrix (BinaryFileInputStream::mk (kFileName_, BinaryFileInputStream::eNotSeekable))) {
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
                DbgTrace (L"***in Instruments::CPU::capture_GetSysTimes_ linesize=%d, line[0]=%s", line.size(), line.empty () ? L"" : line[0].c_str ());
#endif
                if (line.size () >= 5 and line[0] == L"cpu") {
                    result.user = String2Float<double> (line[1]);
                    result.system = String2Float<double> (line[3]);
                    result.idle = String2Float<double> (line[4]);
                    break;  // once found no need to read the rest...
                }
            }
            return result;
        }
        double  cputime_ ()
        {
            POSIXSysTimeCaptureContext_   baseline = fContext_;
            POSIXSysTimeCaptureContext_   newVal = GetSysTimes_ ();
            fContext_ = newVal;

            double  usedSysTime = (newVal.user - baseline.user) + (newVal.system - baseline.system);
            double  totalTime = usedSysTime + (newVal.idle - baseline.idle);
            if (Math::NearlyEquals<double> (totalTime, 0)) {
                // can happen if called too quickly together. No good answer
                DbgTrace ("Warning - times too close together for cputime_");
                return 0;
            }
            Assert (totalTime > 0);
            double cpu =  usedSysTime * 100 / totalTime;
            return Math::PinInRange<double> (cpu, 0, 100);
        }
        Info capture_ ()
        {
            Execution::SleepUntil (fPostponeCaptureUntil_);
            Info    result;
#if     qSupport_SystemPerformance_Instruments_CPU_LoadAverage
            {
                double loadAve[3];
                int lr = ::getloadavg (loadAve, 3);
                if (lr == 3) {
                    result.fLoadAverage = Info::LoadAverage (loadAve[0], loadAve[1], loadAve[2]);
                }
                else {
                    DbgTrace ("getloadave failed - with result = %d", lr);
                }
            }
#endif
            result.fTotalCPUUsage = cputime_ ();
            NoteCompletedCapture_ ();
            return result;
        }
    };
}
#endif

#if   qPlatform_Windows
namespace {
    struct  CapturerWithContext_Windows_ : CapturerWithContext_COMMON_ {
        struct  WinSysTimeCaptureContext_ {
            double  IdleTime;
            double  KernelTime;
            double  UserTime;
        };
        WinSysTimeCaptureContext_   fContext_;
        CapturerWithContext_Windows_ (const Options& options)
            : CapturerWithContext_COMMON_ (options)
        {
            capture_ ();    // Force fill of context
        }
        static  inline  double  GetAsSeconds_ (FILETIME ft)
        {
            ULARGE_INTEGER  ui;
            ui.LowPart = ft.dwLowDateTime;
            ui.HighPart = ft.dwHighDateTime;
            // convert from 100-nanosecond units
            return static_cast<double> (ui.QuadPart) / 10000000;
        }
        static  inline  WinSysTimeCaptureContext_    GetSysTimes_ ()
        {
            FILETIME    curIdleTime_;
            FILETIME    curKernelTime_;
            FILETIME    curUserTime_;
            memset (&curIdleTime_, 0, sizeof (curIdleTime_));
            memset (&curKernelTime_, 0, sizeof (curKernelTime_));
            memset (&curUserTime_, 0, sizeof (curUserTime_));
            Verify (::GetSystemTimes (&curIdleTime_, &curKernelTime_, &curUserTime_));
            return WinSysTimeCaptureContext_ { GetAsSeconds_ (curIdleTime_), GetAsSeconds_ (curKernelTime_), GetAsSeconds_ (curUserTime_) };
        }
        double  cputime_ ()
        {
            /*
             *  This logic seems queer (sys = kern + user, and why isnt numerator userTime?), but is cribbed from
             *      http://en.literateprograms.org/CPU_usage_%28C,_Windows_XP%29
             *      http://www.codeproject.com/Articles/9113/Get-CPU-Usage-with-GetSystemTimes
             */
            WinSysTimeCaptureContext_   baseline = fContext_;
            WinSysTimeCaptureContext_   newVal = GetSysTimes_ ();
            fContext_ = newVal;

            double  idleTimeOverInterval = newVal.IdleTime - baseline.IdleTime;
            double  kernelTimeOverInterval = newVal.KernelTime - baseline.KernelTime;
            double  userTimeOverInterval = newVal.UserTime - baseline.UserTime;

            double sys = kernelTimeOverInterval + userTimeOverInterval;
            Assert (sys > 0);
            double cpu =  (sys - idleTimeOverInterval) * 100 / sys;
            return Math::PinInRange<double> (cpu, 0, 100);
        }
        Info capture_ ()
        {
            Info    result;
            Execution::SleepUntil (fPostponeCaptureUntil_);
            result.fTotalCPUUsage = cputime_ ();
            NoteCompletedCapture_ ();
            return result;
        }
    };
}
#endif

namespace {
    struct  CapturerWithContext_
            : Debug::AssertExternallySynchronizedLock
#if     qPlatform_POSIX
            , CapturerWithContext_POSIX_
#elif   qPlatform_Windows
            , CapturerWithContext_Windows_
#endif
    {
#if     qPlatform_POSIX
        using inherited = CapturerWithContext_POSIX_;
#elif   qPlatform_Windows
        using inherited = CapturerWithContext_Windows_;
#endif
        CapturerWithContext_ (Options options)
            : inherited (options)
        {
        }
        Info capture_ ()
        {
            lock_guard<const AssertExternallySynchronizedLock> critSec { *this };
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
            Debug::TraceContextBumper ctx ("Instruments::CPU capture_");
#endif
            return inherited::capture_ ();
        }
    };
}

/*
 ********************************************************************************
 ************************* Instruments::CPU::GetInstrument **********************
 ********************************************************************************
 */
Instrument  SystemPerformance::Instruments::CPU::GetInstrument (Options options)
{
    CapturerWithContext_ useCaptureContext { options };  // capture context so copyable in mutable lambda
    static  const   MeasurementType kCPUMeasurment_         =   MeasurementType (String_Constant (L"CPU-Usage"));
    return Instrument (
               InstrumentNameType (String_Constant (L"CPU")),
    [useCaptureContext] () mutable -> MeasurementSet {
        MeasurementSet    results;
        DateTime    before = useCaptureContext.fLastCapturedAt;
        Info rawMeasurement = useCaptureContext.capture_ ();
        results.fMeasuredAt = DateTimeRange (before, useCaptureContext.fLastCapturedAt);
        Measurement m;
        m.fValue = GetObjectVariantMapper ().FromObject (rawMeasurement);
        m.fType = kCPUMeasurment_;
        results.fMeasurements.Add (m);
        return results;
    },
    {kCPUMeasurment_},
    GetObjectVariantMapper ()
           );
}
<|endoftext|>


<commit_before>/** Copyright (C) 2016, 2017 European Spallation Source ERIC */

//#include <algorithm>
//#include <memory>
#include <multigrid/mgmesytec/Data.h>
#include <multigrid/mgmesytec/TestData.h>
#include <test/TestBase.h>

class MesytecDataTest : public TestBase {
protected:
  MesytecData mesytec;
  virtual void SetUp() { }
  virtual void TearDown() { }
};

/** Test cases below */

TEST_F(MesytecDataTest, ErrUnsupportedCommand) {
  auto res = mesytec.parse((char *)&err_unsupported_cmd[0], err_unsupported_cmd.size());

  ASSERT_EQ(res, -MesytecData::error::EUNSUPP);
}

TEST_F(MesytecDataTest, ErrPktShort) {
  auto res = mesytec.parse((char *)&err_pkt_too_short[0], err_pkt_too_short.size());

  ASSERT_EQ(res, -MesytecData::error::ESIZE);
}

TEST_F(MesytecDataTest, ParseRecordedWSData) {
  auto res = mesytec.parse((char *)&ws1[0], ws1.size());
  ASSERT_EQ(res, -MesytecData::error::OK);
  ASSERT_EQ(mesytec.readouts, 128 - (128-92)); // Readout provides more than 92 channels
}

TEST_F(MesytecDataTest, ParseRecordedWSDataII) {
  auto res = mesytec.parse((char *)&ws2[0], ws2.size());
  ASSERT_EQ(res, -MesytecData::error::OK);
  ASSERT_EQ(mesytec.readouts, 256 - 2*(128-92)); // Readout provides more than 92 channels
}

TEST_F(MesytecDataTest, ParseRecordedWSDataIII) {
  auto res = mesytec.parse((char *)&ws3[0], ws3.size());
  ASSERT_EQ(res, -MesytecData::error::OK);
  ASSERT_EQ(mesytec.readouts, 256 - 2*(128-92)); // Readout provides more than 92 channels
}

int main(int argc, char **argv) {
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<commit_msg>do not suppress unused channels, for now<commit_after>/** Copyright (C) 2016, 2017 European Spallation Source ERIC */

//#include <algorithm>
//#include <memory>
#include <multigrid/mgmesytec/Data.h>
#include <multigrid/mgmesytec/TestData.h>
#include <test/TestBase.h>

class MesytecDataTest : public TestBase {
protected:
  MesytecData mesytec;
  virtual void SetUp() { }
  virtual void TearDown() { }
};

/** Test cases below */

TEST_F(MesytecDataTest, ErrUnsupportedCommand) {
  auto res = mesytec.parse((char *)&err_unsupported_cmd[0], err_unsupported_cmd.size());

  ASSERT_EQ(res, -MesytecData::error::EUNSUPP);
}

TEST_F(MesytecDataTest, ErrPktShort) {
  auto res = mesytec.parse((char *)&err_pkt_too_short[0], err_pkt_too_short.size());

  ASSERT_EQ(res, -MesytecData::error::ESIZE);
}

TEST_F(MesytecDataTest, ParseRecordedWSData) {
  auto res = mesytec.parse((char *)&ws1[0], ws1.size());
  ASSERT_EQ(res, -MesytecData::error::OK);
  ASSERT_EQ(mesytec.readouts, 128);
}

TEST_F(MesytecDataTest, ParseRecordedWSDataII) {
  auto res = mesytec.parse((char *)&ws2[0], ws2.size());
  ASSERT_EQ(res, -MesytecData::error::OK);
  ASSERT_EQ(mesytec.readouts, 256);
}

TEST_F(MesytecDataTest, ParseRecordedWSDataIII) {
  auto res = mesytec.parse((char *)&ws3[0], ws3.size());
  ASSERT_EQ(res, -MesytecData::error::OK);
  ASSERT_EQ(mesytec.readouts, 256); // Readout provides more than 92 channels
}

int main(int argc, char **argv) {
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>/*
 * InstrumentImplementation.cpp
 *
 *  Created on: 31/10/2010
 *      Author: victor
 */

#include "server/zone/objects/tangible/Instrument.h"
#include "server/zone/objects/tangible/InstrumentObserver.h"
#include "server/zone/objects/creature/CreatureObject.h"
#include "server/zone/packets/object/ObjectMenuResponse.h"
#include "server/zone/objects/player/PlayerObject.h"
#include "server/zone/managers/object/ObjectManager.h"
#include "server/zone/objects/cell/CellObject.h"
#include "server/zone/objects/structure/StructureObject.h"
#include "server/zone/Zone.h"

void InstrumentImplementation::fillObjectMenuResponse(ObjectMenuResponse* menuResponse, CreatureObject* player) {
	if (instrumentType != OMNIBOX && instrumentType != NALARGON)
		return;

	if (canDropInstrument()) {
		ManagedReference<SceneObject*> parent = getParentRecursively(SceneObjectType::PLAYERCREATURE).get();

		if (parent != NULL && parent == player->asSceneObject())
			menuResponse->addRadialMenuItem(20, 3, "@ui_radial:item_use");
	} else {
		if (spawnerPlayer != NULL && spawnerPlayer == player) {
			if (!player->isPlayingMusic())
				menuResponse->addRadialMenuItem(20, 3, "@radial_performance:play_instrument");
			else
				menuResponse->addRadialMenuItem(20, 3, "@radial_performance:stop_playing");
		}
	}
}

int InstrumentImplementation::handleObjectMenuSelect(CreatureObject* player, byte selectedID) {
	if (instrumentType != OMNIBOX && instrumentType != NALARGON)
		return 1;

	if (selectedID != 20)
		return 1;

	if (canDropInstrument()) {
		ManagedReference<SceneObject*> parent = getParentRecursively(SceneObjectType::PLAYERCREATURE).get();

		if (parent == NULL || parent != player->asSceneObject())
			return 1;

		if (player->isSkillAnimating()) {
			player->sendSystemMessage("@performance:music_fail"); // You are unable to do that at this time.
			return 1;
		}

		SortedVector<ManagedReference<Observer* > > observers = player->getObservers(ObserverEventType::POSITIONCHANGED);

		for (int i = 0; i < observers.size(); ++i) {
			InstrumentObserver* observer = dynamic_cast<InstrumentObserver*>(observers.get(i).get());

			if (observer != NULL) {
				ManagedReference<Instrument*> oldInstrument = observer->getInstrument().get();

				if (oldInstrument != NULL) {
					Locker locker(oldInstrument);
					oldInstrument->destroyObjectFromWorld(true);
					player->dropObserver(ObserverEventType::POSITIONCHANGED, observer);
					player->dropObserver(ObserverEventType::OBJECTREMOVEDFROMZONE, observer);
				}
			}
		}

		ManagedReference<SceneObject*> playerParent = player->getParent();

		if (playerParent != NULL) {
			if (!playerParent->isCellObject()) {
				return 1;
			} else {
				CellObject* cell = cast<CellObject*>( playerParent.get());

				StructureObject* structureObject = dynamic_cast<StructureObject*>(cell->getParent().get().get());

				if (structureObject == NULL)
					return 1;

				if (!structureObject->isOnAdminList(player))
					spawnNonAdmin(player);
				else {
					spawnInAdminCell(player);
				}
			}
		} else {
			spawnNonAdmin(player);
		}
	} else {
		if (getZone() == NULL)
			return 1;

		if (spawnerPlayer == NULL || spawnerPlayer != player)
			return 1;

		if (player->isPlayingMusic()) {
			player->executeObjectControllerAction(STRING_HASHCODE("stopmusic"), getObjectID(), "");
		} else {

			Reference<Instrument*> instrument = player->getSlottedObject("hold_r").castTo<Instrument*>();

			if (instrument != NULL) {
				player->sendSystemMessage("@performance:music_must_unequip");
				return 1;
			}

			Reference<PlayerObject*> ghost = player->getSlottedObject("ghost").castTo<PlayerObject*>();

			if (ghost == NULL)
				return 1;

			if (!ghost->hasAbility("startmusic")) {
				player->sendSystemMessage("@performance:music_lack_skill_instrument");
				return 1;
			}

			if (player->getDistanceTo(_this.getReferenceUnsafeStaticCast()) >= 5) {
				player->sendSystemMessage("@elevator_text:too_far");
			} else
				player->executeObjectControllerAction(STRING_HASHCODE("startmusic"), getObjectID(), "");
		}
	}

	return 0;
}

bool InstrumentImplementation::canDropInstrument() {
	ManagedReference<SceneObject*> parent = getParent().get();

	if (isInQuadTree() || (parent != NULL && parent->isCellObject()))
		return false;

	return true;
}

void InstrumentImplementation::spawnNonAdmin(CreatureObject* player) {
	if (spawnedObject == NULL) {
		spawnedObject = ObjectManager::instance()->createObject(serverObjectCRC, 0, "sceneobjects");
		spawnedObject->setParent(NULL);
		spawnedObject->setZone(NULL);
	}

	if (spawnedObject->getZone() == NULL) {
		Instrument* instrument = cast<Instrument*>( spawnedObject.get());

		Locker locker(instrument);

		instrument->initializePosition(player->getPositionX(), player->getPositionZ(), player->getPositionY());
		instrument->setSpawnerPlayer(player);

		ManagedReference<SceneObject*> parent = player->getParent().get();
		Zone* zone = player->getZone();

		if (parent != NULL) {
			parent->transferObject(instrument, -1);
		} else if (zone != NULL) {
			zone->transferObject(instrument, -1, true);
		} else {
			return;
		}

		ManagedReference<InstrumentObserver*> posObserver = new InstrumentObserver(instrument);
		player->registerObserver(ObserverEventType::POSITIONCHANGED, posObserver);
		player->registerObserver(ObserverEventType::OBJECTREMOVEDFROMZONE, posObserver);
	} else {
		spawnedObject->teleport(player->getPositionX(), player->getPositionZ(), player->getPositionY(), player->getParentID());
	}

	spawnerPlayer = player;
}

void InstrumentImplementation::spawnInAdminCell(CreatureObject* player) {
	StringBuffer arguments;
	arguments << player->getParent().get()->getObjectID() << " -1 " << player->getPositionX() << " " << player->getPositionZ() << " " << player->getPositionY();

	UnicodeString uni = arguments.toString();

	player->executeObjectControllerAction(STRING_HASHCODE("transferitemmisc"), _this.getReferenceUnsafeStaticCast()->getObjectID(), uni);

	spawnerPlayer = NULL;

	if (spawnedObject != NULL) {
		Locker locker(spawnedObject);
		spawnedObject->destroyObjectFromWorld(true);
		spawnedObject = NULL;
	}
}
<commit_msg>[fixed] Droppable instrument pickup bug - mantis 6170<commit_after>/*
 * InstrumentImplementation.cpp
 *
 *  Created on: 31/10/2010
 *      Author: victor
 */

#include "server/zone/objects/tangible/Instrument.h"
#include "server/zone/objects/tangible/InstrumentObserver.h"
#include "server/zone/objects/creature/CreatureObject.h"
#include "server/zone/packets/object/ObjectMenuResponse.h"
#include "server/zone/objects/player/PlayerObject.h"
#include "server/zone/managers/object/ObjectManager.h"
#include "server/zone/objects/cell/CellObject.h"
#include "server/zone/objects/structure/StructureObject.h"
#include "server/zone/Zone.h"

void InstrumentImplementation::fillObjectMenuResponse(ObjectMenuResponse* menuResponse, CreatureObject* player) {
	if (instrumentType != OMNIBOX && instrumentType != NALARGON)
		return;

	if (canDropInstrument()) {
		ManagedReference<SceneObject*> parent = getParentRecursively(SceneObjectType::PLAYERCREATURE).get();

		if (parent != NULL && parent == player->asSceneObject())
			menuResponse->addRadialMenuItem(20, 3, "@ui_radial:item_use");
	} else {
		if (spawnerPlayer != NULL && spawnerPlayer == player) {
			if (!player->isPlayingMusic())
				menuResponse->addRadialMenuItem(20, 3, "@radial_performance:play_instrument");
			else
				menuResponse->addRadialMenuItem(20, 3, "@radial_performance:stop_playing");
		}
	}

	TangibleObjectImplementation::fillObjectMenuResponse(menuResponse, player);
}

int InstrumentImplementation::handleObjectMenuSelect(CreatureObject* player, byte selectedID) {
	if (instrumentType != OMNIBOX && instrumentType != NALARGON)
		return 1;

	if (selectedID != 20)
		return 1;

	if (canDropInstrument()) {
		ManagedReference<SceneObject*> parent = getParentRecursively(SceneObjectType::PLAYERCREATURE).get();

		if (parent == NULL || parent != player->asSceneObject())
			return 1;

		if (player->isSkillAnimating()) {
			player->sendSystemMessage("@performance:music_fail"); // You are unable to do that at this time.
			return 1;
		}

		SortedVector<ManagedReference<Observer* > > observers = player->getObservers(ObserverEventType::POSITIONCHANGED);

		for (int i = 0; i < observers.size(); ++i) {
			InstrumentObserver* observer = dynamic_cast<InstrumentObserver*>(observers.get(i).get());

			if (observer != NULL) {
				ManagedReference<Instrument*> oldInstrument = observer->getInstrument().get();

				if (oldInstrument != NULL) {
					Locker locker(oldInstrument);
					oldInstrument->destroyObjectFromWorld(true);
					player->dropObserver(ObserverEventType::POSITIONCHANGED, observer);
					player->dropObserver(ObserverEventType::OBJECTREMOVEDFROMZONE, observer);
				}
			}
		}

		ManagedReference<SceneObject*> playerParent = player->getParent();

		if (playerParent != NULL) {
			if (!playerParent->isCellObject()) {
				return 1;
			} else {
				CellObject* cell = cast<CellObject*>( playerParent.get());

				StructureObject* structureObject = dynamic_cast<StructureObject*>(cell->getParent().get().get());

				if (structureObject == NULL)
					return 1;

				if (!structureObject->isOnAdminList(player))
					spawnNonAdmin(player);
				else {
					spawnInAdminCell(player);
				}
			}
		} else {
			spawnNonAdmin(player);
		}
	} else {
		if (getZone() == NULL)
			return 1;

		if (spawnerPlayer == NULL || spawnerPlayer != player)
			return 1;

		if (player->isPlayingMusic()) {
			player->executeObjectControllerAction(STRING_HASHCODE("stopmusic"), getObjectID(), "");
		} else {

			Reference<Instrument*> instrument = player->getSlottedObject("hold_r").castTo<Instrument*>();

			if (instrument != NULL) {
				player->sendSystemMessage("@performance:music_must_unequip");
				return 1;
			}

			Reference<PlayerObject*> ghost = player->getSlottedObject("ghost").castTo<PlayerObject*>();

			if (ghost == NULL)
				return 1;

			if (!ghost->hasAbility("startmusic")) {
				player->sendSystemMessage("@performance:music_lack_skill_instrument");
				return 1;
			}

			if (player->getDistanceTo(_this.getReferenceUnsafeStaticCast()) >= 5) {
				player->sendSystemMessage("@elevator_text:too_far");
			} else
				player->executeObjectControllerAction(STRING_HASHCODE("startmusic"), getObjectID(), "");
		}
	}

	return 0;
}

bool InstrumentImplementation::canDropInstrument() {
	ManagedReference<SceneObject*> parent = getParent().get();

	if (isInQuadTree() || (parent != NULL && parent->isCellObject()))
		return false;

	return true;
}

void InstrumentImplementation::spawnNonAdmin(CreatureObject* player) {
	if (spawnedObject == NULL) {
		spawnedObject = ObjectManager::instance()->createObject(serverObjectCRC, 0, "sceneobjects");
		spawnedObject->setParent(NULL);
		spawnedObject->setZone(NULL);
	}

	if (spawnedObject->getZone() == NULL) {
		Instrument* instrument = cast<Instrument*>( spawnedObject.get());

		Locker locker(instrument);

		instrument->initializePosition(player->getPositionX(), player->getPositionZ(), player->getPositionY());
		instrument->setSpawnerPlayer(player);

		ManagedReference<SceneObject*> parent = player->getParent().get();
		Zone* zone = player->getZone();

		if (parent != NULL) {
			parent->transferObject(instrument, -1);
		} else if (zone != NULL) {
			zone->transferObject(instrument, -1, true);
		} else {
			return;
		}

		ManagedReference<InstrumentObserver*> posObserver = new InstrumentObserver(instrument);
		player->registerObserver(ObserverEventType::POSITIONCHANGED, posObserver);
		player->registerObserver(ObserverEventType::OBJECTREMOVEDFROMZONE, posObserver);
	} else {
		spawnedObject->teleport(player->getPositionX(), player->getPositionZ(), player->getPositionY(), player->getParentID());
	}

	spawnerPlayer = player;
}

void InstrumentImplementation::spawnInAdminCell(CreatureObject* player) {
	StringBuffer arguments;
	arguments << player->getParent().get()->getObjectID() << " -1 " << player->getPositionX() << " " << player->getPositionZ() << " " << player->getPositionY();

	UnicodeString uni = arguments.toString();

	player->executeObjectControllerAction(STRING_HASHCODE("transferitemmisc"), _this.getReferenceUnsafeStaticCast()->getObjectID(), uni);

	spawnerPlayer = NULL;

	if (spawnedObject != NULL) {
		Locker locker(spawnedObject);
		spawnedObject->destroyObjectFromWorld(true);
		spawnedObject = NULL;
	}
}
<|endoftext|>


<commit_before>#include "AngleControl.h"

AngleControl::AngleControl() {
	// Use requires() here to declare subsystem dependencies
	Requires(shooter);
}

// Called just before this Command runs the first time
void AngleControl::Initialize() {

}

// Called repeatedly when this Command is scheduled to run
void AngleControl::Execute() {
	shooter->SetSpeedAngle(oi->GetDriverStickAxis(false,2));
	SmartDashboard::PutNumber("Shooter Angle", shooter->AnglePotVoltage());
}

// Make this return true when this Command no longer needs to run execute()
bool AngleControl::IsFinished() {
	return false;
}

// Called once after isFinished returns true
void AngleControl::End() {

}

// Called when another command which requires one or more of the same
// subsystems is scheduled to run
void AngleControl::Interrupted() {
}
<commit_msg>Direction change in AngleCtrl, Driver Pref<commit_after>#include "AngleControl.h"

AngleControl::AngleControl() {
	// Use requires() here to declare subsystem dependencies
	Requires(shooter);
}

// Called just before this Command runs the first time
void AngleControl::Initialize() {

}

// Called repeatedly when this Command is scheduled to run
void AngleControl::Execute() {
	shooter->SetSpeedAngle(oi->GetDriverStickAxis(false,2) * -1);
	SmartDashboard::PutNumber("Shooter Angle", shooter->AnglePotVoltage());
}

// Make this return true when this Command no longer needs to run execute()
bool AngleControl::IsFinished() {
	return false;
}

// Called once after isFinished returns true
void AngleControl::End() {

}

// Called when another command which requires one or more of the same
// subsystems is scheduled to run
void AngleControl::Interrupted() {
}
<|endoftext|>


<commit_before>#include "BulletsConverter.h"
#include "StylesWriter.h"

using namespace PPT_FORMAT;

BulletsConverter::BulletsConverter(CRelsGenerator* pRels) : m_pRels(pRels) {}

void BulletsConverter::FillPPr(PPTX::Logic::TextParagraphPr &oPPr, CParagraph &paragraph)
{
    oPPr.lvl = paragraph.m_lTextLevel;

    auto* pPF = &(paragraph.m_oPFRun);
    if (pPF)
        ConvertPFRun(oPPr, pPF);
}

void BulletsConverter::ConvertPFRun(PPTX::Logic::TextParagraphPr &oPPr, CTextPFRun *pPF)
{
    int leftMargin = 0;
    if (pPF->leftMargin.is_init())
    {
        leftMargin = pPF->leftMargin.get();
        oPPr.marL = leftMargin;
    }
    if (pPF->indent.is_init())
    {
        if (pPF->hasBullet.get_value_or(false) && pPF->indent.get() != -leftMargin)
        {
            oPPr.indent = pPF->indent.get() - leftMargin;
        }
        else
        {
            oPPr.indent = pPF->indent.get();
        }
    } else if (pPF->hasBullet.get_value_or(false))
    {
        oPPr.indent = -leftMargin;
    }
    if (pPF->textAlignment.is_init())
    {
        oPPr.algn = new PPTX::Limit::TextAlign;
        oPPr.algn->set(CStylesWriter::GetTextAlign(pPF->textAlignment.get()));
    }
    if (pPF->defaultTabSize.is_init())
    {
        oPPr.defTabSz = pPF->defaultTabSize.get();
    }
    if (pPF->textDirection.is_init())
    {
        if (pPF->textDirection.get() == 1)	oPPr.rtl = true;
        else								oPPr.rtl = false;
    }
    if (pPF->fontAlign.is_init())
    {
        oPPr.fontAlgn = new PPTX::Limit::FontAlign;
        oPPr.fontAlgn->set(CStylesWriter::GetFontAlign(pPF->fontAlign.get()));
    }
    if (pPF->wrapFlags.is_init() && pPF->wrapFlags.get() & 0b111)
    {
        const auto& flags = pPF->wrapFlags.get();
        if (flags & 0b100)
            oPPr.hangingPunct = true;

    }

    ConvertTabStops(oPPr.tabLst, pPF->tabStops);

    if (pPF->lineSpacing.is_init())
    {
        LONG val = pPF->lineSpacing.get();
        auto pLnSpc = new PPTX::Logic::TextSpacing;
        pLnSpc->m_name = L"a:lnSpc";

        if (val > 0)
            pLnSpc->spcPct = val * 12.5;
        else if (val < 0 && val > -13200)
            pLnSpc->spcPct = val * -1000;

        oPPr.lnSpc = pLnSpc;
    }

    if (pPF->spaceAfter.is_init())
    {
        LONG val = pPF->spaceAfter.get();
        auto pSpcAft = new PPTX::Logic::TextSpacing;
        pSpcAft->m_name = L"a:spcAft";
        if (val > 0)
            pSpcAft->spcPts = round(12.5 * pPF->spaceAfter.get());
        else if (val < 0 && val > -13200)
            pSpcAft->spcPts = val * -1000;

        oPPr.spcAft = pSpcAft;
    }
    if (pPF->spaceBefore.is_init())
    {
        LONG val = pPF->spaceBefore.get();
        auto pSpcBef = new PPTX::Logic::TextSpacing;
        pSpcBef->m_name = L"a:spcBef";
        if (val > 0)
            pSpcBef->spcPts = round(12.5 * pPF->spaceBefore.get());
        else if (val < 0 && val > -13200)
            pSpcBef->spcPct = val * -1000;

        oPPr.spcBef = pSpcBef;
    }

    ConvertAllBullets(oPPr, pPF);
}

void BulletsConverter::ConvertTabStops(std::vector<PPTX::Logic::Tab> &arrTabs, std::vector<std::pair<int, int> > &arrTabStops)
{
    for (size_t t = 0 ; t < arrTabStops.size(); t++)
    {
        PPTX::Logic::Tab tab;
        tab.pos = arrTabStops[t].first;
        auto pAlgn = new PPTX::Limit::TextTabAlignType;

        switch (arrTabStops[t].second)
        {
        case 1: pAlgn->set(L"ctr"); break;
        case 2: pAlgn->set(L"r"); break;
        case 3: pAlgn->set(L"dec"); break;
        default: pAlgn->set(L"l");
        }
        tab.algn = pAlgn;

        arrTabs.push_back(tab);
    }
}

void BulletsConverter::FillBuChar(PPTX::Logic::Bullet &oBullet, WCHAR symbol, CTextPFRun *pPF)
{
    auto pBuChar = new PPTX::Logic::BuChar;
    pBuChar->Char.clear();
    if (pPF != nullptr && pPF->bulletFontProperties.IsInit())
    {
        const auto& fontProp = *(pPF->bulletFontProperties);
        if (fontProp.Charset == 10)
        {
            symbol &= 0x00ff;
            symbol |= 0xf000;
        }
    }
    pBuChar->Char.push_back(symbol);
    oBullet.m_Bullet.reset(pBuChar);
}

void BulletsConverter::ConvertAllBullets(PPTX::Logic::TextParagraphPr &oPPr, CTextPFRun *pPF)
{
    if (pPF->hasBullet.is_init())
    {
        if (pPF->hasBullet.get())
        {
            if (pPF->bulletColor.is_init())
            {
                FillBuClr(oPPr.buColor, pPF->bulletColor.get());
            }
            if (pPF->bulletSize.is_init())
            {
                PPTX::WrapperWritingElement* pBuSize(nullptr);
                if (pPF->bulletSize.get() > 24 && pPF->bulletSize.get() < 401)
                {
                    pBuSize = new PPTX::Logic::BuSzPct;
                    static_cast<PPTX::Logic::BuSzPct*>(pBuSize)->val = pPF->bulletSize.get() * 1000 ;
                }
                if (pPF->bulletSize.get() < 0 && pPF->bulletSize.get() > -4001)
                {
                    pBuSize = new PPTX::Logic::BuSzPts;
                    static_cast<PPTX::Logic::BuSzPts*>(pBuSize)->val = - (pPF->bulletSize.get());
                }
                if (pBuSize != nullptr)
                    oPPr.buSize.m_Size = pBuSize;
            }
            if (pPF->bulletFontProperties.is_init())
            {
                auto pBuFont = new PPTX::Logic::TextFont;
                pBuFont->m_name = L"a:buFont";
                pBuFont->typeface = pPF->bulletFontProperties->Name;

                if ( pPF->bulletFontProperties->PitchFamily > 0)
                    pBuFont->pitchFamily = std::to_wstring(pPF->bulletFontProperties->PitchFamily);
                if ( pPF->bulletFontProperties->Charset > 0)
                    pBuFont->charset = std::to_wstring(pPF->bulletFontProperties->Charset);

                oPPr.buTypeface.m_Typeface.reset(pBuFont);
            }

            // Bullets (numbering, else picture, else char, else default)
            if (pPF->bulletBlip.is_init() && pPF->bulletBlip->tmpImagePath.size() && m_pRels != nullptr)
            {
                auto strRID = m_pRels->WriteImage(pPF->bulletBlip->tmpImagePath);
                if (strRID.empty())
                    FillBuChar(oPPr.ParagraphBullet, L'\x2022');    // error rId
                else
                {
                    auto pBuBlip = new PPTX::Logic::BuBlip;
                    pBuBlip->blip.embed = new OOX::RId(strRID);
                    oPPr.ParagraphBullet.m_Bullet.reset(pBuBlip);
                }
            }
            else if (pPF->bulletAutoNum.is_init())
            {
                auto pBuAutoNum = new PPTX::Logic::BuAutoNum;
                oPPr.ParagraphBullet.m_Bullet.reset(pBuAutoNum);
                if (pPF->bulletAutoNum->startAt.is_init() && pPF->bulletAutoNum->startAt.get() != 1)
                    pBuAutoNum->startAt = pPF->bulletAutoNum->startAt.get();
                if (pPF->bulletAutoNum->type.is_init())
                    pBuAutoNum->type = pPF->bulletAutoNum->type.get();
            }
            else if (pPF->bulletChar.is_init())
            {
                FillBuChar(oPPr.ParagraphBullet, pPF->bulletChar.get(), pPF);
            }
            else
            {
                FillBuChar(oPPr.ParagraphBullet, L'\x2022');
            }
        }
        else
        {
            oPPr.buTypeface.m_Typeface.reset(new PPTX::Logic::BuNone);
        }
    }
}

void BulletsConverter::FillBuClr(PPTX::Logic::BulletColor &oBuClr, CColor &oColor)
{
    auto pBuClr = new PPTX::Logic::BuClr;
    pBuClr->Color.SetRGBColor(oColor.GetR(), oColor.GetG(), oColor.GetB());
    oBuClr.m_Color.reset(pBuClr);
}
<commit_msg>fix bug #57029<commit_after>#include "BulletsConverter.h"
#include "StylesWriter.h"

using namespace PPT_FORMAT;

BulletsConverter::BulletsConverter(CRelsGenerator* pRels) : m_pRels(pRels) {}

void BulletsConverter::FillPPr(PPTX::Logic::TextParagraphPr &oPPr, CParagraph &paragraph)
{
    oPPr.lvl = paragraph.m_lTextLevel;

    auto* pPF = &(paragraph.m_oPFRun);
    if (pPF)
        ConvertPFRun(oPPr, pPF);
}

void BulletsConverter::ConvertPFRun(PPTX::Logic::TextParagraphPr &oPPr, CTextPFRun *pPF)
{
    const int oneTabSize = 457200;
    int leftMargin = 0;
    if (pPF->leftMargin.is_init())
    {
        leftMargin = pPF->leftMargin.get();
        oPPr.marL = leftMargin;
    }
    if (pPF->indent.is_init())
    {
        if (pPF->hasBullet.get_value_or(false) && pPF->indent.get() != -leftMargin)
        {
            oPPr.indent = pPF->indent.get() - leftMargin;
        }
        else
        {
            oPPr.indent = pPF->indent.get();
        }
    } else if (pPF->hasBullet.get_value_or(false))
    {
        const int tabLvl = oPPr.lvl.get_value_or(0);
        if (tabLvl != -1)
            oPPr.indent = oneTabSize*tabLvl - leftMargin;
        else
            oPPr.indent = -leftMargin;
    }
    if (pPF->textAlignment.is_init())
    {
        oPPr.algn = new PPTX::Limit::TextAlign;
        oPPr.algn->set(CStylesWriter::GetTextAlign(pPF->textAlignment.get()));
    }
    if (pPF->defaultTabSize.is_init())
    {
        oPPr.defTabSz = pPF->defaultTabSize.get();
    }
    if (pPF->textDirection.is_init())
    {
        if (pPF->textDirection.get() == 1)	oPPr.rtl = true;
        else								oPPr.rtl = false;
    }
    if (pPF->fontAlign.is_init())
    {
        oPPr.fontAlgn = new PPTX::Limit::FontAlign;
        oPPr.fontAlgn->set(CStylesWriter::GetFontAlign(pPF->fontAlign.get()));
    }
    if (pPF->wrapFlags.is_init() && pPF->wrapFlags.get() & 0b111)
    {
        const auto& flags = pPF->wrapFlags.get();
        if (flags & 0b100)
            oPPr.hangingPunct = true;

    }

    ConvertTabStops(oPPr.tabLst, pPF->tabStops);

    if (pPF->lineSpacing.is_init())
    {
        LONG val = pPF->lineSpacing.get();
        auto pLnSpc = new PPTX::Logic::TextSpacing;
        pLnSpc->m_name = L"a:lnSpc";

        if (val > 0)
            pLnSpc->spcPct = val * 12.5;
        else if (val < 0 && val > -13200)
            pLnSpc->spcPct = val * -1000;

        oPPr.lnSpc = pLnSpc;
    }

    if (pPF->spaceAfter.is_init())
    {
        LONG val = pPF->spaceAfter.get();
        auto pSpcAft = new PPTX::Logic::TextSpacing;
        pSpcAft->m_name = L"a:spcAft";
        if (val > 0)
            pSpcAft->spcPts = round(12.5 * pPF->spaceAfter.get());
        else if (val < 0 && val > -13200)
            pSpcAft->spcPts = val * -1000;

        oPPr.spcAft = pSpcAft;
    }
    if (pPF->spaceBefore.is_init())
    {
        LONG val = pPF->spaceBefore.get();
        auto pSpcBef = new PPTX::Logic::TextSpacing;
        pSpcBef->m_name = L"a:spcBef";
        if (val > 0)
            pSpcBef->spcPts = round(12.5 * pPF->spaceBefore.get());
        else if (val < 0 && val > -13200)
            pSpcBef->spcPct = val * -1000;

        oPPr.spcBef = pSpcBef;
    }

    ConvertAllBullets(oPPr, pPF);
}

void BulletsConverter::ConvertTabStops(std::vector<PPTX::Logic::Tab> &arrTabs, std::vector<std::pair<int, int> > &arrTabStops)
{
    for (size_t t = 0 ; t < arrTabStops.size(); t++)
    {
        PPTX::Logic::Tab tab;
        tab.pos = arrTabStops[t].first;
        auto pAlgn = new PPTX::Limit::TextTabAlignType;

        switch (arrTabStops[t].second)
        {
        case 1: pAlgn->set(L"ctr"); break;
        case 2: pAlgn->set(L"r"); break;
        case 3: pAlgn->set(L"dec"); break;
        default: pAlgn->set(L"l");
        }
        tab.algn = pAlgn;

        arrTabs.push_back(tab);
    }
}

void BulletsConverter::FillBuChar(PPTX::Logic::Bullet &oBullet, WCHAR symbol, CTextPFRun *pPF)
{
    auto pBuChar = new PPTX::Logic::BuChar;
    pBuChar->Char.clear();
    if (pPF != nullptr && pPF->bulletFontProperties.IsInit())
    {
        const auto& fontProp = *(pPF->bulletFontProperties);
        if (fontProp.Charset == 10)
        {
            symbol &= 0x00ff;
            symbol |= 0xf000;
        }
    }
    pBuChar->Char.push_back(symbol);
    oBullet.m_Bullet.reset(pBuChar);
}

void BulletsConverter::ConvertAllBullets(PPTX::Logic::TextParagraphPr &oPPr, CTextPFRun *pPF)
{
    if (pPF->hasBullet.is_init())
    {
        if (pPF->hasBullet.get())
        {
            if (pPF->bulletColor.is_init())
            {
                FillBuClr(oPPr.buColor, pPF->bulletColor.get());
            }
            if (pPF->bulletSize.is_init())
            {
                PPTX::WrapperWritingElement* pBuSize(nullptr);
                if (pPF->bulletSize.get() > 24 && pPF->bulletSize.get() < 401)
                {
                    pBuSize = new PPTX::Logic::BuSzPct;
                    static_cast<PPTX::Logic::BuSzPct*>(pBuSize)->val = pPF->bulletSize.get() * 1000 ;
                }
                if (pPF->bulletSize.get() < 0 && pPF->bulletSize.get() > -4001)
                {
                    pBuSize = new PPTX::Logic::BuSzPts;
                    static_cast<PPTX::Logic::BuSzPts*>(pBuSize)->val = - (pPF->bulletSize.get());
                }
                if (pBuSize != nullptr)
                    oPPr.buSize.m_Size = pBuSize;
            }
            if (pPF->bulletFontProperties.is_init())
            {
                auto pBuFont = new PPTX::Logic::TextFont;
                pBuFont->m_name = L"a:buFont";
                pBuFont->typeface = pPF->bulletFontProperties->Name;

                if ( pPF->bulletFontProperties->PitchFamily > 0)
                    pBuFont->pitchFamily = std::to_wstring(pPF->bulletFontProperties->PitchFamily);
                if ( pPF->bulletFontProperties->Charset > 0)
                    pBuFont->charset = std::to_wstring(pPF->bulletFontProperties->Charset);

                oPPr.buTypeface.m_Typeface.reset(pBuFont);
            }

            // Bullets (numbering, else picture, else char, else default)
            if (pPF->bulletBlip.is_init() && pPF->bulletBlip->tmpImagePath.size() && m_pRels != nullptr)
            {
                auto strRID = m_pRels->WriteImage(pPF->bulletBlip->tmpImagePath);
                if (strRID.empty())
                    FillBuChar(oPPr.ParagraphBullet, L'\x2022');    // error rId
                else
                {
                    auto pBuBlip = new PPTX::Logic::BuBlip;
                    pBuBlip->blip.embed = new OOX::RId(strRID);
                    oPPr.ParagraphBullet.m_Bullet.reset(pBuBlip);
                }
            }
            else if (pPF->bulletAutoNum.is_init())
            {
                auto pBuAutoNum = new PPTX::Logic::BuAutoNum;
                oPPr.ParagraphBullet.m_Bullet.reset(pBuAutoNum);
                if (pPF->bulletAutoNum->startAt.is_init() && pPF->bulletAutoNum->startAt.get() != 1)
                    pBuAutoNum->startAt = pPF->bulletAutoNum->startAt.get();
                if (pPF->bulletAutoNum->type.is_init())
                    pBuAutoNum->type = pPF->bulletAutoNum->type.get();
            }
            else if (pPF->bulletChar.is_init())
            {
                FillBuChar(oPPr.ParagraphBullet, pPF->bulletChar.get(), pPF);
            }
            else
            {
                FillBuChar(oPPr.ParagraphBullet, L'\x2022');
            }
        }
        else
        {
            oPPr.buTypeface.m_Typeface.reset(new PPTX::Logic::BuNone);
        }
    }
}

void BulletsConverter::FillBuClr(PPTX::Logic::BulletColor &oBuClr, CColor &oColor)
{
    auto pBuClr = new PPTX::Logic::BuClr;
    pBuClr->Color.SetRGBColor(oColor.GetR(), oColor.GetG(), oColor.GetB());
    oBuClr.m_Color.reset(pBuClr);
}
<|endoftext|>


<commit_before><commit_msg>Commented out unused parameters<commit_after><|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkFEMHeatConduction2D.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

  Portions of this code are covered under the VTK copyright.
  See VTKCopyright.txt or http://www.kitware.com/VTKCopyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "itkFEMHeatConduction2D.h"
#include "itkFEMElementBase.h"

namespace itk {
namespace fem {

FEMHeatConduction2D
::FEMHeatConduction2D()
{
   m_Mesh = FEMMeshType::New();
}

FEMHeatConduction2D
::~FEMHeatConduction2D()
{

}

void
FEMHeatConduction2D
::PrintSelf(std::ostream& os, Indent indent) const
{
  Superclass::PrintSelf(os, indent);
}

void
FEMHeatConduction2D
::AssembleMasterEquation(void)
{

   // Here instantiate all the visitors and
   // send them to walk through the mesh

}

}} // end namespace itk::fem

<commit_msg>ENH: A set of visitors is now intantiated to go an compute stiffness matrices.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkFEMHeatConduction2D.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

  Portions of this code are covered under the VTK copyright.
  See VTKCopyright.txt or http://www.kitware.com/VTKCopyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "itkFEMHeatConduction2D.h"
#include "itkFEMElementTriangleHeatConductionVisitor.h"
#include "itkFEMElementQuadrilateralHeatConductionVisitor.h"

namespace itk {
namespace fem {

FEMHeatConduction2D
::FEMHeatConduction2D()
{
   m_Mesh = FEMMeshType::New();
}

FEMHeatConduction2D
::~FEMHeatConduction2D()
{

}

void
FEMHeatConduction2D
::PrintSelf(std::ostream& os, Indent indent) const
{
  Superclass::PrintSelf(os, indent);
}

void
FEMHeatConduction2D
::AssembleMasterEquation(void)
{

  // Instantiate Visitors

  // Types for Triangles
  typedef itk::fem::FEMElementTriangle<
                            FEMMeshType >  TriangleElementType;

  typedef itk::fem::FEMElementTriangleHeatConductionVisitor<
                            FEMMeshType >  TriangleHeatConductionVisitorType;

  typedef itk::fem::FEMElementVisitorImplementation<
                                        FEMMeshType,
                                        TriangleElementType,
                                        TriangleHeatConductionVisitorType
                                            >  TriangleHeatConductionVisitorImplementationType;

  TriangleHeatConductionVisitorImplementationType::Pointer triangleVisitor =
                                  TriangleHeatConductionVisitorImplementationType::New();

  // Types for Quadrilaterals
  typedef itk::fem::FEMElementQuadrilateral<
                            FEMMeshType >  QuadrilateralElementType;

  typedef itk::fem::FEMElementQuadrilateralHeatConductionVisitor<
                            FEMMeshType >  QuadrilateralHeatConductionVisitorType;

  typedef itk::fem::FEMElementVisitorImplementation<
                                        FEMMeshType,
                                        QuadrilateralElementType,
                                        QuadrilateralHeatConductionVisitorType
                                            >  QuadrilateralHeatConductionVisitorImplementationType;

  QuadrilateralHeatConductionVisitorImplementationType::Pointer quadrilateralVisitor =
                                  QuadrilateralHeatConductionVisitorImplementationType::New();

  triangleVisitor->SetMesh( m_Mesh );
  quadrilateralVisitor->SetMesh( m_Mesh );

  // Create a MultiVisitor
  typedef FEMMeshType::ElementMultiVisitorType       MultiVisitorType;

  MultiVisitorType::Pointer multiVisitor    = MultiVisitorType::New();

  multiVisitor->AddVisitor( triangleVisitor );
  multiVisitor->AddVisitor( quadrilateralVisitor );

  // Now ask the mesh to accept the multivisitor which
  // will Call Visit for each cell in the mesh that matches the
  // cell types of the visitors added to the MultiVisitor
  m_Mesh->Accept( multiVisitor );

  std::cout << "Heat Conduction Visitors Done ! " << std::endl;

}

}} // end namespace itk::fem

<|endoftext|>


<commit_before>#include "pch.h"
#include "NativeFileHelper.h"
#include "FileHelper.h"
#include "StringHelper.h"

#include <string>
#include <vector>
#include <stack>
#include <iostream>
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>

using namespace FileComponent;
using namespace Platform;
using namespace Windows::Storage;

using namespace Platform;

/** 写文件0=失败，1=成功，2=写入长度不正确 */
int writeFile(Platform::String^ strPath, char *data, int length) {
	HANDLE hFile;

	char *DataBuffer = data;

	DWORD dwBytesToWrite = length;
	DWORD dwBytesWritten = 0;
	BOOL bErrorFlag = FALSE;

	hFile = CreateFile2(strPath->Data(),
		GENERIC_WRITE,
		FILE_SHARE_READ,
		CREATE_ALWAYS,
		NULL);

	int result = 0;
	if (hFile != INVALID_HANDLE_VALUE) {
		bErrorFlag = WriteFile(
			hFile,
			DataBuffer,
			dwBytesToWrite,
			&dwBytesWritten,
			NULL);

		if (bErrorFlag != FALSE)
		{
			if (dwBytesWritten != dwBytesToWrite)
			{
				result = 2;
				printf("Error: dwBytesWritten != dwBytesToWrite\n");
			}
			else
			{
				result = 1;
			}
		}
	}
	CloseHandle(hFile);
	return result;
}

Platform::Array<byte>^ readFile(Platform::String ^strPath)
{
	HANDLE pfile = CreateFile2(strPath->Data(),                // name of the write
		GENERIC_READ,          // open for writing
		FILE_SHARE_READ,		// do not share
		OPEN_EXISTING,			// default security
		NULL);                  // no attr. template

	LARGE_INTEGER  fileSize;
	GetFileSizeEx(pfile, &fileSize);
	int64 size = fileSize.QuadPart;
	char* buffer = new char[size]; // 最后一位为 '/0',C-Style 字符串的结束符

	DWORD readsize;

	ReadFile(pfile, buffer, size, &readsize, NULL);
	CloseHandle(pfile);

	byte *byteData = (byte *)buffer;
	Platform::Array<byte>^ result = ref new Platform::Array<byte>(byteData, size);

	delete[] buffer;
	return result;
}

unsigned __int64 getFolderSize(std::wstring path, std::wstring mask) {
	HANDLE hFind = INVALID_HANDLE_VALUE;
	WIN32_FIND_DATA ffd;
	std::wstring spec;
	std::stack<std::wstring> directories;

	directories.push(path);

	unsigned __int64 result = 0;

	while (!directories.empty()) {
		path = directories.top();
		spec = path + L"\\" + mask;
		directories.pop();

		hFind = FindFirstFileEx(spec.c_str(), FindExInfoStandard, &ffd, FINDEX_SEARCH_OPS::FindExSearchNameMatch, NULL, FIND_FIRST_EX_LARGE_FETCH);
		if (hFind == INVALID_HANDLE_VALUE) {
			return result;
		}

		do {
			if (wcscmp(ffd.cFileName, L".") != 0 &&
				wcscmp(ffd.cFileName, L"..") != 0) {
				if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
					directories.push(path + L"\\" + ffd.cFileName);
				}
				else {
					//This is file name
					result += ffd.nFileSizeLow + (ffd.nFileSizeHigh * MAXDWORD);
					//files.push_back(path + "\\" + ffd.cFileName);
				}
			}
		} while (FindNextFile(hFind, &ffd) != 0);

		if (GetLastError() != ERROR_NO_MORE_FILES) {
			FindClose(hFind);
			return result;
		}

		FindClose(hFind);
		hFind = INVALID_HANDLE_VALUE;
	}

	return result;
}

int NativeFileHelper::FileExists(Platform::String^ pathOfFolder)
{
	DWORD ftyp = GetFileAttributesW(pathOfFolder->Data());
	if (ftyp != INVALID_FILE_ATTRIBUTES && !(ftyp & FILE_ATTRIBUTE_DIRECTORY))
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

int NativeFileHelper::DirectoryExists(Platform::String^ pathOfFolder)
{
	DWORD ftyp = GetFileAttributesW(pathOfFolder->Data());
	if (ftyp != INVALID_FILE_ATTRIBUTES && (ftyp & FILE_ATTRIBUTE_DIRECTORY))
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

std::wstring getDirectory(std::wstring path)
{
	return path.substr(0, path.find_last_of(L"/\\"));
}

int NativeFileHelper::RemoveFile(Platform::String^ pathOfFile)
{
	int result = ::DeleteFile(pathOfFile->Data());
	if (result != 0) {
		return 1;
	}
	else {
		return 0;
	}
}

uint64 NativeFileHelper::GetFolderSize(Platform::String^ pathOfFolder)
{
	return getFolderSize(pathOfFolder->Data(), L"*");
}

uint64 NativeFileHelper::GetFileSize(Platform::String^ pathOfFile)
{
	HANDLE pfile = CreateFile2(pathOfFile->Data(),                // name of the write
		GENERIC_READ,          // open for writing
		FILE_SHARE_READ,		// do not share
		OPEN_EXISTING,			// default security
		NULL);                  // no attr. template

	LARGE_INTEGER  fileSize;
	GetFileSizeEx(pfile, &fileSize);
	return fileSize.QuadPart;
}

int removeDirectory(const std::wstring &strDir)
{
	WIN32_FIND_DATA fdFile;
	::memset(&fdFile, 0, sizeof(fdFile));

	HANDLE hFind = INVALID_HANDLE_VALUE;

	std::wstring strSearch = strDir + L"\\*.*";
	hFind = ::FindFirstFile(strSearch.data(), &fdFile);

	if (hFind == INVALID_HANDLE_VALUE) {
		return 0;
	}

	do {
		std::wstring strDelete = strDir + L"\\" + fdFile.cFileName;

		if (isDirectory(fdFile) == TRUE) {
			if (isDots(fdFile.cFileName) == TRUE) {
				continue;
			}
			removeDirectory(strDelete);
		}
		else {

			::DeleteFile(strDelete.data());
		}

	} while (::FindNextFile(hFind, &fdFile) == TRUE);

	::FindClose(hFind);
	::RemoveDirectory(strDir.data());

	return 1;
}

int NativeFileHelper::RemoveDirectory(Platform::String^ pathOfFolder)
{
	return removeDirectory(pathOfFolder->Data());
}

/** 写文件，返回值：0=失败，1=成功，2=写入长度不正确 */
int NativeFileHelper::WriteFile(Platform::String^ pathOfFolder, const Platform::Array<byte>^ data)
{
	//如果目录不存在则创建
	const std::wstring directory = getDirectory(pathOfFolder->Data());
	CreateDirectoryW(directory.c_str(), NULL);

	uint32 length = data->Length;
	unsigned char* content = data->Data;
	char *charContent = (char *)content;

	return writeFile(pathOfFolder, charContent, length);
}

Platform::Array<byte>^ NativeFileHelper::ReadFile(Platform::String^ pathOfFile)
{
	return readFile(pathOfFile);
}

/** 获取文件夹子项目：1=当前目录文件，2=当前目录文件夹，3=当前目录所有子文件（含子文件夹） */
Platform::Array<Platform::String^>^ getSubItems(Platform::String^ pathOfFolder, BOOL isDirectory)
{
	std::wstring path = pathOfFolder->Data();

	HANDLE hFind = INVALID_HANDLE_VALUE;
	WIN32_FIND_DATA ffd;
	std::wstring spec;

	Platform::Collections::Vector<Platform::String^>^ items = ref new  Platform::Collections::Vector<Platform::String^>();

	unsigned __int64 result = 0;

	spec = path + L"\\*";

	hFind = FindFirstFileEx(spec.c_str(), FindExInfoStandard, &ffd, FINDEX_SEARCH_OPS::FindExSearchNameMatch, NULL, FIND_FIRST_EX_LARGE_FETCH);
	if (hFind == INVALID_HANDLE_VALUE) {
		return ref new Platform::Array<Platform::String^>(0);
	}

	do {
		if (wcscmp(ffd.cFileName, L".") != 0 && wcscmp(ffd.cFileName, L"..") != 0) {
			if (isDirectory == TRUE) {
				//文件夹
				if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
					items->Append(ref new Platform::String((path + L"\\" + ffd.cFileName).c_str()));
				}
			}
			else  if (!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
				//文件
				items->Append(ref new Platform::String((path + L"\\" + ffd.cFileName).c_str()));
			}
		}
	} while (FindNextFile(hFind, &ffd) != 0);

	if (GetLastError() == ERROR_NO_MORE_FILES) {
		FindClose(hFind);

		Platform::Array<Platform::String^>^ array = ref new Platform::Array<Platform::String^>(items->Size);
		int i = 0;
		for each (Platform::String^ item in items)
		{
			array[i] = item;
			i++;
		}
		return array;
	}
	else {
		FindClose(hFind);
		return ref new Platform::Array<Platform::String^>(0);
	}
}

Platform::Array<Platform::String^>^ NativeFileHelper::GetSubFiles(Platform::String^ pathOfFolder)
{
	return getSubItems(pathOfFolder, FALSE);
}

Platform::Array<Platform::String^>^ NativeFileHelper::GetSubDirectories(Platform::String^ pathOfFolder)
{
	return getSubItems(pathOfFolder, TRUE);
}

//int NativeFileHelper::RenameItem(Platform::String^ source, Platform::String^ dest)
//{
//	//如果目录不存在则创建
//	const std::wstring directory = getDirectory(dest->Data());
//	CreateDirectoryW(directory.c_str(), NULL);
//
//	return MoveFileExW(source->Data(),
//		dest->Data(), NULL);
//}

Platform::Array<Platform::String^>^ NativeFileHelper::GetAllFiles(Platform::String^ pathOfFolder)
{
	std::wstring path = pathOfFolder->Data();

	HANDLE hFind = INVALID_HANDLE_VALUE;
	WIN32_FIND_DATA ffd;
	std::wstring spec;
	std::stack<std::wstring> directories;

	Platform::Collections::Vector<Platform::String^>^ files = ref new  Platform::Collections::Vector<Platform::String^>();

	directories.push(path);

	unsigned __int64 result = 0;

	while (!directories.empty()) {
		path = directories.top();
		spec = path + L"\\*";
		directories.pop();

		hFind = FindFirstFileEx(spec.c_str(), FindExInfoStandard, &ffd, FINDEX_SEARCH_OPS::FindExSearchNameMatch, NULL, FIND_FIRST_EX_LARGE_FETCH);
		if (hFind == INVALID_HANDLE_VALUE) {
			return ref new Platform::Array<Platform::String^>(0);
		}

		do {
			if (wcscmp(ffd.cFileName, L".") != 0 && wcscmp(ffd.cFileName, L"..") != 0) {
				if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
					directories.push(path + L"\\" + ffd.cFileName);
				}
				else {
					files->Append(ref new Platform::String((path + L"\\" + ffd.cFileName).c_str()));
				}
			}
		} while (FindNextFile(hFind, &ffd) != 0);

		if (GetLastError() != ERROR_NO_MORE_FILES) {
			FindClose(hFind);
		}

		FindClose(hFind);
		hFind = INVALID_HANDLE_VALUE;
	}

	Platform::Array<Platform::String^>^ array = ref new Platform::Array<Platform::String^>(files->Size);
	int i = 0;
	for each (Platform::String^ item in files)
	{
		array[i] = item;
		i++;
	}
	return array;
}<commit_msg>fix readfile bug, update nuget<commit_after>#include "pch.h"
#include "NativeFileHelper.h"
#include "FileHelper.h"
#include "StringHelper.h"

#include <string>
#include <vector>
#include <stack>
#include <iostream>
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>

using namespace FileComponent;
using namespace Platform;
using namespace Windows::Storage;

using namespace Platform;

/** 写文件0=失败，1=成功，2=写入长度不正确 */
int writeFile(Platform::String^ strPath, char *data, int length) {
	HANDLE hFile;

	char *DataBuffer = data;

	DWORD dwBytesToWrite = length;
	DWORD dwBytesWritten = 0;
	BOOL bErrorFlag = FALSE;

	hFile = CreateFile2(strPath->Data(),
		GENERIC_WRITE,
		FILE_SHARE_READ,
		CREATE_ALWAYS,
		NULL);

	int result = 0;
	if (hFile != INVALID_HANDLE_VALUE) {
		bErrorFlag = WriteFile(
			hFile,
			DataBuffer,
			dwBytesToWrite,
			&dwBytesWritten,
			NULL);

		if (bErrorFlag != FALSE)
		{
			if (dwBytesWritten != dwBytesToWrite)
			{
				result = 2;
				printf("Error: dwBytesWritten != dwBytesToWrite\n");
			}
			else
			{
				result = 1;
			}
		}
	}
	CloseHandle(hFile);
	return result;
}

Platform::Array<byte>^ readFile(Platform::String ^strPath)
{
	DWORD ftyp = GetFileAttributesW(strPath->Data());
	if (ftyp != INVALID_FILE_ATTRIBUTES && !(ftyp & FILE_ATTRIBUTE_DIRECTORY))
	{
		HANDLE pfile = CreateFile2(strPath->Data(),                // name of the write
			GENERIC_READ,          // open for writing
			FILE_SHARE_READ,		// do not share
			OPEN_EXISTING,			// default security
			NULL);                  // no attr. template

		LARGE_INTEGER  fileSize;
		GetFileSizeEx(pfile, &fileSize);
		int64 size = fileSize.QuadPart;
		char* buffer = new char[size]; // 最后一位为 '/0',C-Style 字符串的结束符

		DWORD readsize;

		ReadFile(pfile, buffer, size, &readsize, NULL);
		CloseHandle(pfile);

		byte *byteData = (byte *)buffer;
		Platform::Array<byte>^ result = ref new Platform::Array<byte>(byteData, size);

		delete[] buffer;
		return result;
	}
	else {
		return nullptr;
	}
}

unsigned __int64 getFolderSize(std::wstring path, std::wstring mask) {
	HANDLE hFind = INVALID_HANDLE_VALUE;
	WIN32_FIND_DATA ffd;
	std::wstring spec;
	std::stack<std::wstring> directories;

	directories.push(path);

	unsigned __int64 result = 0;

	while (!directories.empty()) {
		path = directories.top();
		spec = path + L"\\" + mask;
		directories.pop();

		hFind = FindFirstFileEx(spec.c_str(), FindExInfoStandard, &ffd, FINDEX_SEARCH_OPS::FindExSearchNameMatch, NULL, FIND_FIRST_EX_LARGE_FETCH);
		if (hFind == INVALID_HANDLE_VALUE) {
			return result;
		}

		do {
			if (wcscmp(ffd.cFileName, L".") != 0 &&
				wcscmp(ffd.cFileName, L"..") != 0) {
				if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
					directories.push(path + L"\\" + ffd.cFileName);
				}
				else {
					//This is file name
					result += ffd.nFileSizeLow + (ffd.nFileSizeHigh * MAXDWORD);
					//files.push_back(path + "\\" + ffd.cFileName);
				}
			}
		} while (FindNextFile(hFind, &ffd) != 0);

		if (GetLastError() != ERROR_NO_MORE_FILES) {
			FindClose(hFind);
			return result;
		}

		FindClose(hFind);
		hFind = INVALID_HANDLE_VALUE;
	}

	return result;
}

int NativeFileHelper::FileExists(Platform::String^ pathOfFolder)
{
	DWORD ftyp = GetFileAttributesW(pathOfFolder->Data());
	if (ftyp != INVALID_FILE_ATTRIBUTES && !(ftyp & FILE_ATTRIBUTE_DIRECTORY))
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

int NativeFileHelper::DirectoryExists(Platform::String^ pathOfFolder)
{
	DWORD ftyp = GetFileAttributesW(pathOfFolder->Data());
	if (ftyp != INVALID_FILE_ATTRIBUTES && (ftyp & FILE_ATTRIBUTE_DIRECTORY))
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

std::wstring getDirectory(std::wstring path)
{
	return path.substr(0, path.find_last_of(L"/\\"));
}

int NativeFileHelper::RemoveFile(Platform::String^ pathOfFile)
{
	int result = ::DeleteFile(pathOfFile->Data());
	if (result != 0) {
		return 1;
	}
	else {
		return 0;
	}
}

uint64 NativeFileHelper::GetFolderSize(Platform::String^ pathOfFolder)
{
	return getFolderSize(pathOfFolder->Data(), L"*");
}

uint64 NativeFileHelper::GetFileSize(Platform::String^ pathOfFile)
{
	HANDLE pfile = CreateFile2(pathOfFile->Data(),                // name of the write
		GENERIC_READ,          // open for writing
		FILE_SHARE_READ,		// do not share
		OPEN_EXISTING,			// default security
		NULL);                  // no attr. template

	LARGE_INTEGER  fileSize;
	GetFileSizeEx(pfile, &fileSize);
	return fileSize.QuadPart;
}

int removeDirectory(const std::wstring &strDir)
{
	WIN32_FIND_DATA fdFile;
	::memset(&fdFile, 0, sizeof(fdFile));

	HANDLE hFind = INVALID_HANDLE_VALUE;

	std::wstring strSearch = strDir + L"\\*.*";
	hFind = ::FindFirstFile(strSearch.data(), &fdFile);

	if (hFind == INVALID_HANDLE_VALUE) {
		return 0;
	}

	do {
		std::wstring strDelete = strDir + L"\\" + fdFile.cFileName;

		if (isDirectory(fdFile) == TRUE) {
			if (isDots(fdFile.cFileName) == TRUE) {
				continue;
			}
			removeDirectory(strDelete);
		}
		else {

			::DeleteFile(strDelete.data());
		}

	} while (::FindNextFile(hFind, &fdFile) == TRUE);

	::FindClose(hFind);
	::RemoveDirectory(strDir.data());

	return 1;
}

int NativeFileHelper::RemoveDirectory(Platform::String^ pathOfFolder)
{
	return removeDirectory(pathOfFolder->Data());
}

/** 写文件，返回值：0=失败，1=成功，2=写入长度不正确 */
int NativeFileHelper::WriteFile(Platform::String^ pathOfFolder, const Platform::Array<byte>^ data)
{
	//如果目录不存在则创建
	const std::wstring directory = getDirectory(pathOfFolder->Data());
	CreateDirectoryW(directory.c_str(), NULL);

	uint32 length = data->Length;
	unsigned char* content = data->Data;
	char *charContent = (char *)content;

	return writeFile(pathOfFolder, charContent, length);
}

Platform::Array<byte>^ NativeFileHelper::ReadFile(Platform::String^ pathOfFile)
{
	return readFile(pathOfFile);
}

/** 获取文件夹子项目：1=当前目录文件，2=当前目录文件夹，3=当前目录所有子文件（含子文件夹） */
Platform::Array<Platform::String^>^ getSubItems(Platform::String^ pathOfFolder, BOOL isDirectory)
{
	std::wstring path = pathOfFolder->Data();

	HANDLE hFind = INVALID_HANDLE_VALUE;
	WIN32_FIND_DATA ffd;
	std::wstring spec;

	Platform::Collections::Vector<Platform::String^>^ items = ref new  Platform::Collections::Vector<Platform::String^>();

	unsigned __int64 result = 0;

	spec = path + L"\\*";

	hFind = FindFirstFileEx(spec.c_str(), FindExInfoStandard, &ffd, FINDEX_SEARCH_OPS::FindExSearchNameMatch, NULL, FIND_FIRST_EX_LARGE_FETCH);
	if (hFind == INVALID_HANDLE_VALUE) {
		return ref new Platform::Array<Platform::String^>(0);
	}

	do {
		if (wcscmp(ffd.cFileName, L".") != 0 && wcscmp(ffd.cFileName, L"..") != 0) {
			if (isDirectory == TRUE) {
				//文件夹
				if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
					items->Append(ref new Platform::String((path + L"\\" + ffd.cFileName).c_str()));
				}
			}
			else  if (!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
				//文件
				items->Append(ref new Platform::String((path + L"\\" + ffd.cFileName).c_str()));
			}
		}
	} while (FindNextFile(hFind, &ffd) != 0);

	if (GetLastError() == ERROR_NO_MORE_FILES) {
		FindClose(hFind);

		Platform::Array<Platform::String^>^ array = ref new Platform::Array<Platform::String^>(items->Size);
		int i = 0;
		for each (Platform::String^ item in items)
		{
			array[i] = item;
			i++;
		}
		return array;
	}
	else {
		FindClose(hFind);
		return ref new Platform::Array<Platform::String^>(0);
	}
}

Platform::Array<Platform::String^>^ NativeFileHelper::GetSubFiles(Platform::String^ pathOfFolder)
{
	return getSubItems(pathOfFolder, FALSE);
}

Platform::Array<Platform::String^>^ NativeFileHelper::GetSubDirectories(Platform::String^ pathOfFolder)
{
	return getSubItems(pathOfFolder, TRUE);
}

//int NativeFileHelper::RenameItem(Platform::String^ source, Platform::String^ dest)
//{
//	//如果目录不存在则创建
//	const std::wstring directory = getDirectory(dest->Data());
//	CreateDirectoryW(directory.c_str(), NULL);
//
//	return MoveFileExW(source->Data(),
//		dest->Data(), NULL);
//}

Platform::Array<Platform::String^>^ NativeFileHelper::GetAllFiles(Platform::String^ pathOfFolder)
{
	std::wstring path = pathOfFolder->Data();

	HANDLE hFind = INVALID_HANDLE_VALUE;
	WIN32_FIND_DATA ffd;
	std::wstring spec;
	std::stack<std::wstring> directories;

	Platform::Collections::Vector<Platform::String^>^ files = ref new  Platform::Collections::Vector<Platform::String^>();

	directories.push(path);

	unsigned __int64 result = 0;

	while (!directories.empty()) {
		path = directories.top();
		spec = path + L"\\*";
		directories.pop();

		hFind = FindFirstFileEx(spec.c_str(), FindExInfoStandard, &ffd, FINDEX_SEARCH_OPS::FindExSearchNameMatch, NULL, FIND_FIRST_EX_LARGE_FETCH);
		if (hFind == INVALID_HANDLE_VALUE) {
			return ref new Platform::Array<Platform::String^>(0);
		}

		do {
			if (wcscmp(ffd.cFileName, L".") != 0 && wcscmp(ffd.cFileName, L"..") != 0) {
				if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
					directories.push(path + L"\\" + ffd.cFileName);
				}
				else {
					files->Append(ref new Platform::String((path + L"\\" + ffd.cFileName).c_str()));
				}
			}
		} while (FindNextFile(hFind, &ffd) != 0);

		if (GetLastError() != ERROR_NO_MORE_FILES) {
			FindClose(hFind);
		}

		FindClose(hFind);
		hFind = INVALID_HANDLE_VALUE;
	}

	Platform::Array<Platform::String^>^ array = ref new Platform::Array<Platform::String^>(files->Size);
	int i = 0;
	for each (Platform::String^ item in files)
	{
		array[i] = item;
		i++;
	}
	return array;
}<|endoftext|>