This commit is contained in:
qiluo-msft 2015-03-23 14:29:01 +08:00
Родитель af9d02bcb8
Коммит b5e500bdda
1325 изменённых файлов: 346442 добавлений и 1005 удалений

2
DebugTool/dirs Normal file
Просмотреть файл

@ -0,0 +1,2 @@
DIRS = \
source

Просмотреть файл

@ -0,0 +1,80 @@
#include <Windows.h>
#include <algorithm>
#include <math.h>
#include "AppendArray.h"
using namespace std;
inline size_t RoundUpToPowerOf2(size_t num32)
{
num32--;
num32 |= num32 >> 1;
num32 |= num32 >> 2;
num32 |= num32 >> 4;
num32 |= num32 >> 8;
num32 |= num32 >> 16;
#if _WIN64
num32 |= num32 >> 32;
#endif
num32++;
return num32;
}
AppendArray::AppendArray()
{
dataSize = 0;
currentCapacity = MIN_ALLOC_COUNT;
currentBufIdx = 0;
currentFreeSize = currentCapacity;
buffer.push_back(new char[currentCapacity]);
currentPtrInBuf = buffer[0];
}
AppendArray::~AppendArray()
{
for_each(buffer.begin(), buffer.end(), [](char * ptr){
delete [] ptr;
});
}
void AppendArray::Add(char * str)
{
size_t sizeNeeded = strlen(str) + 1;
if (sizeNeeded > currentFreeSize)
{
size_t sizeNeededRounded = RoundUpToPowerOf2(sizeNeeded);
size_t newSize = max(sizeNeededRounded, currentFreeSize * 2);
char * newBuf = new char[newSize];
buffer.push_back(newBuf);
currentBufIdx++;
currentCapacity = newSize;
currentFreeSize = newSize;
currentPtrInBuf = newBuf;
}
memcpy(currentPtrInBuf, str, sizeNeeded);
indexList.push_back(currentPtrInBuf);
currentPtrInBuf += sizeNeeded;
currentFreeSize -= sizeNeeded;
dataSize += sizeNeeded;
}
char * AppendArray::GetPtr(size_t index)
{
if (index >= indexList.size())
return 0;
else
return indexList[index];
}
size_t AppendArray::RecordCount()
{
return indexList.size();
}
size_t AppendArray::DataSize()
{
return dataSize;
}

Просмотреть файл

@ -0,0 +1,28 @@
#pragma once
#include <vector>
#include <deque>
using namespace std;
class AppendArray
{
public:
AppendArray();
~AppendArray();
void Add(char *);
char * GetPtr(size_t index);
size_t RecordCount();
size_t DataSize();
private:
static const size_t MIN_ALLOC_COUNT = 1024;
size_t allocCnt;
vector<char *> buffer;
int currentBufIdx;
size_t currentCapacity;
size_t currentFreeSize;
char * currentPtrInBuf;
deque<char *> indexList;
size_t dataSize;
};

Просмотреть файл

@ -0,0 +1,31 @@
#pragma once
#include <Windows.h>
namespace SoraDbgPlot { namespace Lock {
class CSLock
{
public:
CSLock() {
::InitializeCriticalSection(&_cs);
}
~CSLock()
{
::DeleteCriticalSection(&_cs);
}
void Lock()
{
::EnterCriticalSection(&_cs);
}
void Unlock()
{
::LeaveCriticalSection(&_cs);
}
private:
CRITICAL_SECTION _cs;
};
}}

Просмотреть файл

@ -0,0 +1,46 @@
#pragma once
#include <Windows.h>
#include "CSLock.h"
namespace SoraDbgPlot { namespace Lock {
class CSRecursiveLock
{
public:
CSRecursiveLock()
{
_tid = 0;
_recursiveCount = 0;
}
~CSRecursiveLock()
{
}
void Lock()
{
DWORD tid = ::GetCurrentThreadId();
if (tid != _tid)
{
_lock.Lock();
_tid = tid;
}
::InterlockedIncrement(&_recursiveCount);
}
void Unlock()
{
if (::InterlockedDecrement(&_recursiveCount) == 0)
{
_tid = 0;
_lock.Unlock();
}
}
private:
CSLock _lock;
volatile DWORD _tid;
volatile unsigned long _recursiveCount;
};
}};

Просмотреть файл

@ -0,0 +1,138 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{54730AD7-5B11-493B-ADCC-8E4EC3C0204A}</ProjectGuid>
<SccProjectName>
</SccProjectName>
<SccAuxPath>
</SccAuxPath>
<SccLocalPath>
</SccLocalPath>
<SccProvider>
</SccProvider>
<Keyword>Win32Proj</Keyword>
<RootNamespace>Common</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<CallingConvention>StdCall</CallingConvention>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType>
<AdditionalIncludeDirectories>..\..\..\kernel\core\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType>
<AdditionalIncludeDirectories>..\..\..\kernel\core\inc</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<None Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="AppendArray.h" />
<ClInclude Include="CSLock.h" />
<ClInclude Include="CSRecursiveLock.h" />
<ClInclude Include="DACL_Control.h" />
<ClInclude Include="DataQueue.h" />
<ClInclude Include="DynamicArray.h" />
<ClInclude Include="ErrMsg.h" />
<ClInclude Include="Event.h" />
<ClInclude Include="FileHelper.h" />
<ClInclude Include="FrameWithSizeFilter.h" />
<ClInclude Include="ILog.h" />
<ClInclude Include="LogWithFileBackup.h" />
<ClInclude Include="PathName.h" />
<ClInclude Include="ReadWriteLock.h" />
<ClInclude Include="RingBuffer.h" />
<ClInclude Include="RingBufferWithTimeStamp.h" />
<ClInclude Include="Runnable.h" />
<ClInclude Include="RWTaskQueue.h" />
<ClInclude Include="SharedSerialNumGenerator.h" />
<ClInclude Include="ShareMemHelper.h" />
<ClInclude Include="std_memory.h" />
<ClInclude Include="Strategy.h" />
<ClInclude Include="TaskCoordinator.h" />
<ClInclude Include="TaskSimple.h" />
<ClInclude Include="TaskQueue.h" />
<ClInclude Include="TaskQueueRequester.h" />
<ClInclude Include="TempBuffer.h" />
<ClInclude Include="TimeStampQueue.h" />
<ClInclude Include="WaitableLatestTaskQueue.h" />
<ClInclude Include="Writable.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="AppendArray.cpp" />
<ClCompile Include="ErrMsg.cpp" />
<ClCompile Include="Event.cpp" />
<ClCompile Include="FileHelper.cpp" />
<ClCompile Include="ILog.cpp" />
<ClCompile Include="LogWithFileBackup.cpp" />
<ClCompile Include="PathName.cpp" />
<ClCompile Include="TaskQueue.cpp" />
<ClCompile Include="TempBuffer.cpp" />
<ClCompile Include="TimeStampQueue.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

Просмотреть файл

@ -0,0 +1,193 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Log">
<UniqueIdentifier>{d7de7e63-403d-468c-ae31-cb43d834bcc1}</UniqueIdentifier>
</Filter>
<Filter Include="AppendArray">
<UniqueIdentifier>{f9426287-32ec-4f24-bdfb-b719d5d38965}</UniqueIdentifier>
</Filter>
<Filter Include="RingBuffer">
<UniqueIdentifier>{fc77e29f-4bdd-4951-973b-295d85eb5b26}</UniqueIdentifier>
</Filter>
<Filter Include="DataFilter">
<UniqueIdentifier>{bb7b48c6-b159-4fb8-b6dc-a5e3f41d9703}</UniqueIdentifier>
</Filter>
<Filter Include="Writable">
<UniqueIdentifier>{862eed55-ae25-4b28-af1d-c773eb9971c3}</UniqueIdentifier>
</Filter>
<Filter Include="DynamicArray">
<UniqueIdentifier>{69a8d289-e1e5-4349-b585-dfb2d180add3}</UniqueIdentifier>
</Filter>
<Filter Include="SerialNum">
<UniqueIdentifier>{b62095c5-01a4-41d8-9ed4-a1215883d951}</UniqueIdentifier>
</Filter>
<Filter Include="Event">
<UniqueIdentifier>{a3428d2b-5505-429f-9ff7-3d7bf05e8119}</UniqueIdentifier>
</Filter>
<Filter Include="Task">
<UniqueIdentifier>{90ae29f2-86bf-40a4-a539-45457b4e9332}</UniqueIdentifier>
</Filter>
<Filter Include="Strategy">
<UniqueIdentifier>{0b385ccb-5070-4328-94f8-2773ab93eb4f}</UniqueIdentifier>
</Filter>
<Filter Include="DataQueue">
<UniqueIdentifier>{f670156b-c3ab-478f-8a0d-9787ab6d4d33}</UniqueIdentifier>
</Filter>
<Filter Include="Lock">
<UniqueIdentifier>{f0a99025-3248-4449-8231-de5bf5547fce}</UniqueIdentifier>
</Filter>
<Filter Include="Task\Runnable">
<UniqueIdentifier>{809e8963-bea5-4180-ab7f-7abadf5225be}</UniqueIdentifier>
</Filter>
<Filter Include="Task\Runnable\Task">
<UniqueIdentifier>{e2a5e64f-6ff5-48f1-be7a-996abef6fa54}</UniqueIdentifier>
</Filter>
<Filter Include="Helper">
<UniqueIdentifier>{92f04332-33c6-41d2-b4bb-7133f29947c3}</UniqueIdentifier>
</Filter>
<Filter Include="ShareMem">
<UniqueIdentifier>{a2fa4a28-d584-4423-8e92-6e0b6bed1490}</UniqueIdentifier>
</Filter>
<Filter Include="TempBuffer">
<UniqueIdentifier>{6253eabc-0081-4011-a347-4d053d11f599}</UniqueIdentifier>
</Filter>
<Filter Include="File">
<UniqueIdentifier>{21350b9f-d893-4900-9bf2-91ced0a7d001}</UniqueIdentifier>
</Filter>
<Filter Include="ErrMsg">
<UniqueIdentifier>{677a99bb-78fa-47e0-9684-348cb22031c7}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<None Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="ILog.h">
<Filter>Log</Filter>
</ClInclude>
<ClInclude Include="LogWithFileBackup.h">
<Filter>Log</Filter>
</ClInclude>
<ClInclude Include="AppendArray.h">
<Filter>AppendArray</Filter>
</ClInclude>
<ClInclude Include="RingBuffer.h">
<Filter>RingBuffer</Filter>
</ClInclude>
<ClInclude Include="RingBufferWithTimeStamp.h">
<Filter>RingBuffer</Filter>
</ClInclude>
<ClInclude Include="TimeStampQueue.h">
<Filter>RingBuffer</Filter>
</ClInclude>
<ClInclude Include="FrameWithSizeFilter.h">
<Filter>DataFilter</Filter>
</ClInclude>
<ClInclude Include="Writable.h">
<Filter>Writable</Filter>
</ClInclude>
<ClInclude Include="DynamicArray.h">
<Filter>DynamicArray</Filter>
</ClInclude>
<ClInclude Include="SharedSerialNumGenerator.h">
<Filter>SerialNum</Filter>
</ClInclude>
<ClInclude Include="Event.h">
<Filter>Event</Filter>
</ClInclude>
<ClInclude Include="WaitableLatestTaskQueue.h">
<Filter>Task</Filter>
</ClInclude>
<ClInclude Include="Strategy.h">
<Filter>Strategy</Filter>
</ClInclude>
<ClInclude Include="DataQueue.h">
<Filter>DataQueue</Filter>
</ClInclude>
<ClInclude Include="CSLock.h">
<Filter>Lock</Filter>
</ClInclude>
<ClInclude Include="TaskQueue.h">
<Filter>Task</Filter>
</ClInclude>
<ClInclude Include="CSRecursiveLock.h">
<Filter>Lock</Filter>
</ClInclude>
<ClInclude Include="ReadWriteLock.h">
<Filter>Lock</Filter>
</ClInclude>
<ClInclude Include="RWTaskQueue.h">
<Filter>Task</Filter>
</ClInclude>
<ClInclude Include="TaskQueueRequester.h">
<Filter>Task</Filter>
</ClInclude>
<ClInclude Include="Runnable.h">
<Filter>Task\Runnable</Filter>
</ClInclude>
<ClInclude Include="TaskCoordinator.h">
<Filter>Task\Runnable\Task</Filter>
</ClInclude>
<ClInclude Include="TaskSimple.h">
<Filter>Task\Runnable\Task</Filter>
</ClInclude>
<ClInclude Include="std_memory.h">
<Filter>Helper</Filter>
</ClInclude>
<ClInclude Include="TempBuffer.h">
<Filter>TempBuffer</Filter>
</ClInclude>
<ClInclude Include="FileHelper.h">
<Filter>File</Filter>
</ClInclude>
<ClInclude Include="PathName.h">
<Filter>File</Filter>
</ClInclude>
<ClInclude Include="ErrMsg.h">
<Filter>ErrMsg</Filter>
</ClInclude>
<ClInclude Include="DACL_Control.h">
<Filter>ShareMem</Filter>
</ClInclude>
<ClInclude Include="ShareMemHelper.h">
<Filter>ShareMem</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="LogWithFileBackup.cpp">
<Filter>Log</Filter>
</ClCompile>
<ClCompile Include="ILog.cpp">
<Filter>Log</Filter>
</ClCompile>
<ClCompile Include="AppendArray.cpp">
<Filter>AppendArray</Filter>
</ClCompile>
<ClCompile Include="TimeStampQueue.cpp">
<Filter>RingBuffer</Filter>
</ClCompile>
<ClCompile Include="TaskQueue.cpp">
<Filter>Task</Filter>
</ClCompile>
<ClCompile Include="Event.cpp">
<Filter>Event</Filter>
</ClCompile>
<ClCompile Include="TempBuffer.cpp">
<Filter>TempBuffer</Filter>
</ClCompile>
<ClCompile Include="FileHelper.cpp">
<Filter>File</Filter>
</ClCompile>
<ClCompile Include="PathName.cpp">
<Filter>File</Filter>
</ClCompile>
<ClCompile Include="ErrMsg.cpp">
<Filter>ErrMsg</Filter>
</ClCompile>
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,10 @@
""
{
"FILE_VERSION" = "9237"
"ENLISTMENT_CHOICE" = "NEVER"
"PROJECT_FILE_RELATIVE_PATH" = ""
"NUMBER_OF_EXCLUDED_FILES" = "0"
"ORIGINAL_PROJECT_FILE_PATH" = ""
"NUMBER_OF_NESTED_PROJECTS" = "0"
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
}

Просмотреть файл

@ -0,0 +1,20 @@
#include <Windows.h>
#include <Sddl.h>
static inline BOOL CreateDACLWithAllAccess(SECURITY_ATTRIBUTES * pSA)
{
char * szSD = "D:" // Discretionary ACL
"(A;OICI;GA;;;BG)" // full control to built-in guests
"(A;OICI;GA;;;AN)" // full control to anonymous logon
"(A;OICI;GA;;;AU)" // Allow full control to authenticated users
"(A;OICI;GA;;;BA)"; // Allow full control to administrators
if (NULL == pSA)
return FALSE;
return ConvertStringSecurityDescriptorToSecurityDescriptorA(
szSD,
SDDL_REVISION_1,
&(pSA->lpSecurityDescriptor),
NULL);
}

Просмотреть файл

@ -0,0 +1,102 @@
#pragma once
#include <Windows.h>
#include <functional>
#include <vector>
namespace SoraDbgPlot { namespace DataQueue {
class DataQueue
{
public:
struct DataItem
{
char * ptr;
size_t length;
};
DataQueue(size_t size)
{
::InitializeCriticalSection(&_cs);
_index = 0;
_size = 0;
_list = new DataItem[size];
for (size_t i = 0; i < size; i++)
{
_list[i].ptr = 0;
_list[i].length = 0;
}
_capacity = size;
}
~DataQueue()
{
Clear();
delete [] _list;
::DeleteCriticalSection(&_cs);
}
void Clear()
{
this->Read([this](const char * ptr, size_t length){
delete [] ptr;
});
}
void Write(const char * ptr, size_t length)
{
Lock();
if (_size < _capacity)
{
_index = (_index + 1) % _capacity;
_size = min(_size + 1, _capacity);
DataItem & item = _list[_index];
item.ptr = new char[length];
item.length = length;
memcpy(item.ptr, ptr, length);
}
Unlock();
}
void Read(const std::function<void(const char * ptr, const size_t length)> & f)
{
Lock();
size_t start = _index - _size + 1;
while(_size > 0)
{
DataItem & item = _list[start % _capacity];
ASSERT(item.ptr);
f(item.ptr, item.length);
//delete [] item.ptr;
//item.ptr = 0;
//item.length = 0;
start++;
_size--;
}
Unlock();
}
private:
void Lock() {
::EnterCriticalSection(&_cs);
}
void Unlock()
{
::LeaveCriticalSection(&_cs);
}
DataItem * _list;
size_t _index;
size_t _size;
size_t _capacity;
CRITICAL_SECTION _cs;
};
}}

Просмотреть файл

@ -0,0 +1,87 @@
#pragma once
#include <assert.h>
#include <vector>
namespace SoraDbgPlot
{
class DynamicArray // a slow implementation
{
public:
DynamicArray()
{
_capacity = 4096;
_buffer = new char[_capacity];
_wPtr = _buffer;
}
~DynamicArray()
{
delete [] _buffer;
}
void Write(const void * ptr, size_t size, size_t & countWritten)
{
size_t sizeUsable = SizeUsable();
if (size > sizeUsable)
{
size_t sizeRequired = (size - sizeUsable) + _capacity;
size_t sizeReallocate = 1;
while(sizeReallocate < sizeRequired)
sizeReallocate *= 2;
Reallocate(sizeReallocate);
assert(SizeUsable() >= size);
}
memcpy(_wPtr, ptr, size);
_wPtr += size;
countWritten = size;
}
void Reserve(size_t count)
{
Reallocate(count);
}
void Reset()
{
_wPtr = _buffer;
}
size_t Size()
{
return _wPtr - _buffer;
}
const void * Ptr()
{
return _buffer;
}
private:
size_t SizeUsable()
{
return _capacity - (_wPtr - _buffer);
}
void Reallocate(size_t size)
{
if (size <= _capacity)
return;
char * newBuffer = new char[size];
size_t sizeToCopy = _wPtr - _buffer;
if (sizeToCopy > 0)
memcpy(newBuffer, _buffer, sizeToCopy);
delete [] _buffer;
_buffer = newBuffer;
_capacity = size;
_wPtr = _buffer + sizeToCopy;
}
char * _buffer;
size_t _capacity;
char * _wPtr;
};
}

Просмотреть файл

@ -0,0 +1,56 @@
#include "ErrMsg.h"
#include <Windows.h>
#include <stdarg.h>
using namespace SoraDbgPlot::Msg;
const int Message::MAX_MSG_SIZE = 1024;
Message::Message()
{
_tmpBuf = new wchar_t[MAX_MSG_SIZE];
Reset();
}
Message::~Message()
{
if (_tmpBuf)
delete [] _tmpBuf;
}
void Message::Append(const wchar_t * format, ...)
{
va_list ap;
va_start(ap, format);
vswprintf_s(_tmpBuf, MAX_MSG_SIZE, format, ap);
va_end(ap);
_tmpBuf[MAX_MSG_SIZE - 1] = 0;
wchar_t * ptr = _tmpBuf;
wchar_t c;
while( (c = *ptr++) != 0 )
{
_msg.push_back(c);
}
}
void Message::Reset()
{
_msg.clear();
}
Message::operator const wchar_t *()
{
if(_msg.size() == 0)
{
_msg.push_back(0);
}
else if (_msg[_msg.size()-1] != 0)
{
_msg.push_back(0);
}
return &_msg[0];
}

Просмотреть файл

@ -0,0 +1,23 @@
#pragma once
#include <wchar.h>
#include <vector>
#include <functional>
namespace SoraDbgPlot { namespace Msg {
class Message
{
public:
Message();
~Message();
void Append(const wchar_t * format, ...);
void Reset();
operator const wchar_t *();
private:
std::vector<wchar_t> _msg;
static const int MAX_MSG_SIZE;
wchar_t * _tmpBuf;
};
}}

Просмотреть файл

@ -0,0 +1,38 @@
#include "Event.h"
static volatile long __eventHandlerCount = 0;
using namespace SoraDbgPlot::Event;
#ifdef _DEBUG
int __stdcall SoraDbgPlot::Event::EventHandlerCount()
{
return __eventHandlerCount;
}
void __stdcall SoraDbgPlot::Event::EventHandlerCountModify(int count, int sign)
{
if (count == 1)
{
if (sign)
::InterlockedIncrement(&__eventHandlerCount);
else
::InterlockedDecrement(&__eventHandlerCount);
}
else
{
if (sign == 0)
count = -count;
while(1)
{
int ori = __eventHandlerCount;
int target = __eventHandlerCount + count;
if (::InterlockedCompareExchange(&__eventHandlerCount, target, ori) == ori)
break;
}
}
}
#endif

Просмотреть файл

@ -0,0 +1,112 @@
#pragma once
#include <map>
#include <algorithm>
#include <functional>
#include <memory>
#include <Windows.h>
#include "CSRecursiveLock.h"
namespace SoraDbgPlot { namespace Event {
#define CALLBACK_TYPE std::function<void(const void *, const T &)>
#ifdef _DEBUG
int __stdcall EventHandlerCount();
void __stdcall EventHandlerCountModify(int count, int sign);
#endif
template <typename T>
class Event
{
public:
Event()
{
#ifdef _DEBUG
_fortest = new char[13];
#endif
}
~Event()
{
Reset();
}
HANDLE Subscribe(const std::function<void(const void *, const T &)> & f) {
auto fp = std::make_shared<CALLBACK_TYPE>(f);
_lock.Lock();
_callbacks.insert(
std::make_pair(
(HANDLE)fp.get(), fp
)
);
#ifdef _DEBUG
SoraDbgPlot::Event::EventHandlerCountModify(1, true);
#endif
_lock.Unlock();
return (HANDLE)fp.get();
}
bool UnSubscribe(HANDLE h) {
bool ret = false;
_lock.Lock();
auto iter = _callbacks.find(h);
if (iter != _callbacks.end())
{
_callbacks.erase(iter);
#ifdef _DEBUG
SoraDbgPlot::Event::EventHandlerCountModify(1, 0);
#endif
ret = true;
}
_lock.Unlock();
return ret;
}
void Raise(const void * sender, const T & e) const {
_lock.Lock();
std::for_each(_callbacks.begin(), _callbacks.end(), [sender, e](std::pair<HANDLE, std::shared_ptr<CALLBACK_TYPE> > pair){
(*(pair.second))(sender, e);
});
_lock.Unlock();
}
void Reset()
{
_lock.Lock();
int handlerCount = _callbacks.size();
_callbacks.clear();
#ifdef _DEBUG
SoraDbgPlot::Event::EventHandlerCountModify(handlerCount, 0);
if (_fortest) {
delete [] _fortest;
_fortest = 0;
}
#endif
_lock.Unlock();
}
private:
std::map<HANDLE, std::shared_ptr<CALLBACK_TYPE > > _callbacks;
mutable SoraDbgPlot::Lock::CSRecursiveLock _lock;
#ifdef _DEBUG
char * _fortest;
#endif
};
#undef CALLBACK_TYPE
}}

Просмотреть файл

@ -0,0 +1,41 @@
#include "FileHelper.h"
bool SoraDbgPlot::File::CreateDirectoryRecursive(const wchar_t * __folder)
{
bool bSucc;
wchar_t * folderDup = _wcsdup(__folder);
int strlength = wcslen(folderDup);
// remove the last '\'
if ( *(folderDup + strlength - 1) == '\\' )
folderDup[strlength - 1] = 0;
wchar_t * ptr = (wchar_t *)(folderDup + strlength - 1);
while(ptr > folderDup && *ptr != '\\')
--ptr;
if (ptr == folderDup) // root
bSucc = true;
else
{
*ptr = 0;
bSucc = CreateDirectoryRecursive(folderDup);
if (bSucc)
{
*ptr = '\\';
BOOL bRes = CreateDirectoryW(folderDup, NULL);
if (!bRes && GetLastError() != ERROR_ALREADY_EXISTS)
bSucc = false;
bSucc = true;
}
else
bSucc = false;
}
delete [] folderDup;
return bSucc;
}

Просмотреть файл

@ -0,0 +1,9 @@
#pragma once
#include <Windows.h>
namespace SoraDbgPlot { namespace File {
bool CreateDirectoryRecursive(const wchar_t * __folder);
}}

Просмотреть файл

@ -0,0 +1,407 @@
#pragma once
#include <Windows.h>
#include "Writable.h"
#include "DynamicArray.h"
#include "RingBufferWithTimeStamp.h"
#include "Event.h"
#include "ErrMsg.h"
namespace SoraDbgPlot
{
template <typename T>
class FrameWithSizeInfoWriter
{
public:
struct FlushDataEvent { char * ptr; size_t length; unsigned long long timestamp; };
SoraDbgPlot::Event::Event<FlushDataEvent> EventFlushData;
public:
FrameWithSizeInfoWriter(RingBufferWithTimeStamp<T> * writable)
{
_writable = writable;
_dynamicArray = new SoraDbgPlot::DynamicArray();
Init();
}
FrameWithSizeInfoWriter()
{
_writable = 0;
_dynamicArray = new SoraDbgPlot::DynamicArray();
Init();
}
~FrameWithSizeInfoWriter()
{
delete _dynamicArray;
}
void Init()
{
_idExpected = 0;
_sizeTarget = 0;
_timestamp = (unsigned long long)-1;
_bDiscardFlag = false;
_bFirstPackage = true;
_state = &_getSizeState;
}
void Write(const void * ptr, size_t size, size_t & sizeWritten)
{
#ifdef DEBUG_INTERNAL_DATAFILTER
_msg.Reset();
#endif
assert(_state == &_getSizeState);
char * ptrC = (char *)ptr;
do {
size_t sizeProcessed;
_state->Handle(ptrC, size, sizeProcessed, this);
ptrC += sizeProcessed;
size -= sizeProcessed;
} while(size > 0);
}
private:
size_t _sizeTarget;
RingBufferWithTimeStamp<T> * _writable;
DynamicArray * _dynamicArray;
unsigned long long _timestamp;
private:
void FlushBufferIfTestPassed()
{
if (_bDiscardFlag)
{
#ifdef DEBUG_INTERNAL_DATAFILTER
_msg.Append(L"Discard data: %d bytes\n", _dynamicArray->Size());
ReportErrorState();
_msg.Reset();
#endif
return;
}
if (_writable)
_writable->Write((const T *)_dynamicArray->Ptr(), _dynamicArray->Size() / sizeof(T), _timestamp);
FlushDataEvent e;
e.ptr = (char *)_dynamicArray->Ptr();
e.length = _dynamicArray->Size();
e.timestamp = _timestamp;
this->EventFlushData.Raise(this, e);
_dynamicArray->Reset();
}
template <typename T>
class State
{
public:
virtual void Handle(
const void * ptr,
size_t size,
size_t & sizeProcessed,
FrameWithSizeInfoWriter<T> * context) = 0;
};
template <typename T>
class GetSizeState : public State<T>
{
public:
void Handle(
const void * ptr,
size_t size,
size_t & sizeProcessed,
FrameWithSizeInfoWriter<T> * context)
{
const size_t sizeExpected = sizeof(__int16);
#ifdef DEBUG_INTERNAL_DATAFILTER
context->_msg.Reset();
context->_msg.Append(L"h(g, %d)", size);
#endif
if (size < sizeExpected)
{
#ifdef DEBUG_INTERNAL_DATAFILTER
context->_msg.Append(L"e(1, %d)", size);
#endif
context->_state = &context->_errorState;
sizeProcessed = 0;
return;
}
__int16 sizeTarget = *(__int16 *)ptr;
#ifdef DEBUG_INTERNAL_DATAFILTER
context->_msg.Append(L"(%d, %d)", sizeTarget, sizeTarget % (64*sizeof(int)));
#endif
if (sizeTarget == 0)
{
sizeProcessed = sizeExpected;
return;
}
else if ((int)sizeTarget == -1)
{
context->_dynamicArray->Reset();
sizeProcessed = sizeExpected;
return;
}
else
{
context->_sizeTarget = sizeTarget;
context->_state = &context->_getIdState;
sizeProcessed = sizeExpected;
return;
}
}
};
template <typename T>
class GetIdState : public State<T>
{
public:
void Handle(
const void * ptr,
size_t size,
size_t & sizeProcessed,
FrameWithSizeInfoWriter<T> * context)
{
#ifdef DEBUG_INTERNAL_DATAFILTER
context->_msg.Reset();
context->_msg.Append(L"h(id, %d)", size);
#endif
size_t sizeExpected = sizeof(__int16);
if (size < sizeExpected)
{
#ifdef DEBUG_INTERNAL_DATAFILTER
context->_msg.Append(L"e(2, %d)", size);
#endif
context->_state = &context->_errorState;
sizeProcessed = 0;
return;
}
__int16 id = *(__int16 *)ptr;
#ifdef DEBUG_INTERNAL_DATAFILTER
context->_msg.Append(L"(%d)", id);
#endif
if (id == context->_idExpected)
context->_idExpected++;
else
{
context->_bDiscardFlag = true;
#ifdef DEBUG_INTERNAL_DATAFILTER
context->_msg.Append(L"Id Error\n");
context->_msg.Append(L"%d expected, %d got\n", context->_idExpected, id);
context->ReportErrorState();
context->_msg.Reset();
#endif
}
if (id == 0) // first packet
{
context->_bDiscardFlag = false;
context->_dynamicArray->Reset();
context->_bFirstPackage = true;
}
else
context->_bFirstPackage = false;
context->_state = &context->_getTimeStampState;
sizeProcessed = sizeExpected;
return;
}
};
template <typename T>
class GetTimeStampState : public State<T>
{
public:
void Handle(
const void * ptr,
size_t size,
size_t & sizeProcessed,
FrameWithSizeInfoWriter<T> * context)
{
size_t sizeExpected = sizeof(unsigned long long);
#ifdef DEBUG_INTERNAL_DATAFILTER
context->_msg.Append(L"h(t, %d)", size);
#endif
if (size < sizeExpected)
{
#ifdef DEBUG_INTERNAL_DATAFILTER
context->_msg.Append(L"e(1, %d)", size);
#endif
context->_state = &context->_errorState;
sizeProcessed = 0;
return;
}
unsigned long long timestamp = *(unsigned long long *)ptr;
#ifdef DEBUG_INTERNAL_DATAFILTER
context->_msg.Append(L"(%I64d)", timestamp);
#endif
if (context->_bFirstPackage) // check timestamp increment
{
if ( (timestamp < context->_timestamp) && (context->_timestamp != (unsigned long long)(-1)) )
{
#ifdef DEBUG_INTERNAL_DATAFILTER
context->_msg.Append(L"timestamp Error\n");
context->_msg.Append(L"last timestamp is %I64d, but current is %I64d\n", context->_timestamp, timestamp);
context->ReportErrorState();
context->_msg.Reset();
#endif
context->_bDiscardFlag = true;
}
}
else if ( (timestamp != context->_timestamp) ) // check if timestamp is the same
{
#ifdef DEBUG_INTERNAL_DATAFILTER
context->_msg.Append(L"timestamp Error\n");
context->_msg.Append(L"%I64d expected, %I64d got\n", context->_timestamp, timestamp);
context->ReportErrorState();
context->_msg.Reset();
#endif
context->_bDiscardFlag = true;
}
context->_timestamp = timestamp;
context->_state = &context->_saveDataState;
sizeProcessed = sizeExpected;
return;
}
};
template <typename T>
class SaveDataState : public State<T>
{
public:
void Handle(
const void * ptr,
size_t size,
size_t & sizeProcessed,
FrameWithSizeInfoWriter<T> * context)
{
#ifdef DEBUG_INTERNAL_DATAFILTER
context->_msg.Append(L"h(s, %d)", size);
#endif
size_t sizeToWrite = context->_sizeTarget
- sizeof(__int16) // id
- sizeof(unsigned long long) // timestamp
- sizeof(char); // controlFlag
if (size < sizeToWrite)
{
#ifdef DEBUG_INTERNAL_DATAFILTER
context->_msg.Append(L"e(1, %d)", sizeToWrite);
#endif
context->_state = &context->_errorState;
sizeProcessed = 0;
return;
}
else
{
size_t discard;
context->_dynamicArray->Write(ptr, sizeToWrite, discard);
context->_state = &context->_getControlFlagState;
sizeProcessed = sizeToWrite;
return;
}
}
};
template <typename T>
class GetControlFlagState : public State<T>
{
public:
void Handle(
const void * ptr,
size_t size,
size_t & sizeProcessed,
FrameWithSizeInfoWriter<T> * context)
{
#ifdef DEBUG_INTERNAL_DATAFILTER
context->_msg.Append(L"h(c, %d)\n", size);
#endif
if (size < sizeof(char))
{
#ifdef DEBUG_INTERNAL_DATAFILTER
context->_msg.Append(L"e(1, %d)", size);
#endif
context->_state = &context->_errorState;
sizeProcessed = 0;
return;
}
char controlFlag = *(char *)ptr;
if (controlFlag == 1)
{
context->FlushBufferIfTestPassed();
context->_idExpected = 0;
}
context->_state = &context->_getSizeState;
sizeProcessed = 1;
}
};
template <typename T>
class ErrorState : public State<T>
{
void Handle(
const void * ptr,
size_t size,
size_t & sizeProcessed,
FrameWithSizeInfoWriter<T> * context)
{
#ifdef DEBUG_INTERNAL_DATAFILTER
context->_msg.Append(L"Fatal Error!\n");
context->_msg.Append(L"############\n");
context->ReportErrorState();
#endif
context->_dynamicArray->Reset();
context->_state = &context->_getSizeState;
sizeProcessed = size;
}
};
State<T> * _state;
GetSizeState<T> _getSizeState;
GetIdState<T> _getIdState;
GetTimeStampState<T> _getTimeStampState;
SaveDataState<T> _saveDataState;
GetControlFlagState<T> _getControlFlagState;
ErrorState<T> _errorState;
bool _bDiscardFlag;
bool _bFirstPackage;
__int16 _idExpected;
#ifdef DEBUG_INTERNAL_DATAFILTER
void ReportErrorState()
{
::OutputDebugString(L"Data Filter error\n");
::OutputDebugString((const wchar_t *)_msg);
}
#endif
SoraDbgPlot::Msg::Message _msg;
};
}

Просмотреть файл

@ -0,0 +1,140 @@
#pragma once
template <typename Key, typename Value>
class HashEntry
{
public:
HashEntry();
HashEntry(Key key, Value value);
Key key;
Value value;
HashEntry<Key, Value> * _next;
};
template <typename Key, typename Value>
HashEntry<Key, Value>::HashEntry() :
_next(0)
{}
template <typename Key, typename Value>
HashEntry<Key, Value>::HashEntry(Key key, Value value) :
_next(0)
{
this->key = key;
this->value = value;
}
template <typename Key, typename Value, int _hashTableSize, unsigned long (*HashCodeFcn)(Key key), bool (*EqualKey)(Key key1, Key key2)>
class SimpleHashTable
{
public:
SimpleHashTable();
~SimpleHashTable();
void Insert(Key key, Value value);
HashEntry<Key, Value> * Find(Key key);
void Foreach(bool (*VisitorFunc)(Key key, Value value));
void Clear();
private:
HashEntry<Key, Value> * hashBucket[_hashTableSize];
void InsertToList(HashEntry<Key, Value> ** ppEntryHead, HashEntry<Key, Value> * pEntryToInsert);
HashEntry<Key, Value> ** HashCode2EntryListHead(unsigned long hashCode);
void DeleteEntryList(HashEntry<Key, Value> ** ppEntry);
};
template <typename Key, typename Value, int _hashTableSize, unsigned long (*HashCodeFcn)(Key key), bool (*EqualKey)(Key key1, Key key2)>
SimpleHashTable<Key, Value, _hashTableSize, HashCodeFcn, EqualKey>::SimpleHashTable()
{
for (int i = 0; i < _hashTableSize; i++)
{
hashBucket[i] = 0;
}
}
template <typename Key, typename Value, int _hashTableSize, unsigned long (*HashCodeFcn)(Key key), bool (*EqualKey)(Key key1, Key key2)>
SimpleHashTable<Key, Value, _hashTableSize, HashCodeFcn, EqualKey>::~SimpleHashTable()
{
Clear();
}
template <typename Key, typename Value, int _hashTableSize, unsigned long (*HashCodeFcn)(Key key), bool (*EqualKey)(Key key1, Key key2)>
void SimpleHashTable<Key, Value, _hashTableSize, HashCodeFcn, EqualKey>::Clear()
{
for (int i = 0; i < _hashTableSize; i++)
{
DeleteEntryList(this->hashBucket + i);
}
}
template <typename Key, typename Value, int _hashTableSize, unsigned long (*HashCodeFcn)(Key key), bool (*EqualKey)(Key key1, Key key2)>
void SimpleHashTable<Key, Value, _hashTableSize, HashCodeFcn, EqualKey>::DeleteEntryList(HashEntry<Key, Value> ** ppEntry)
{
if (*ppEntry == 0)
return;
DeleteEntryList(&(*ppEntry)->_next);
delete *ppEntry;
*ppEntry = 0;
}
template <typename Key, typename Value, int _hashTableSize, unsigned long (*HashCodeFcn)(Key key), bool (*EqualKey)(Key key1, Key key2)>
void SimpleHashTable<Key, Value, _hashTableSize, HashCodeFcn, EqualKey>::Insert(Key key, Value value)
{
HashEntry<Key, Value> ** ppHashEntryListHead = HashCode2EntryListHead(HashCodeFcn(key));
HashEntry<Key, Value> * hashEntry = new HashEntry<Key, Value>(key, value);
InsertToList(ppHashEntryListHead, hashEntry);
}
template <typename Key, typename Value, int _hashTableSize, unsigned long (*HashCodeFcn)(Key key), bool (*EqualKey)(Key key1, Key key2)>
HashEntry<Key, Value> ** SimpleHashTable<Key, Value, _hashTableSize, HashCodeFcn, EqualKey>::HashCode2EntryListHead(unsigned long hashCode)
{
return this->hashBucket + hashCode % _hashTableSize;
}
template <typename Key, typename Value, int _hashTableSize, unsigned long (*HashCodeFcn)(Key key), bool (*EqualKey)(Key key1, Key key2)>
void SimpleHashTable<Key, Value, _hashTableSize, HashCodeFcn, EqualKey>::InsertToList(HashEntry<Key, Value> ** ppEntryHead, HashEntry<Key, Value> * pEntryToInsert)
{
HashEntry<Key, Value> * pEntryHead = *ppEntryHead;
if (pEntryHead == 0)
{
*ppEntryHead = pEntryToInsert;
}
else
{
HashEntry<Key, Value> * p = pEntryHead;
while(p->_next != 0) p = p->_next;
p->_next = pEntryToInsert;
}
}
template <typename Key, typename Value, int _hashTableSize, unsigned long (*HashCodeFcn)(Key key), bool (*EqualKey)(Key key1, Key key2)>
HashEntry<Key, Value> * SimpleHashTable<Key, Value, _hashTableSize, HashCodeFcn, EqualKey>::Find(Key key)
{
HashEntry<Key, Value> ** ppHashEntryListHead = HashCode2EntryListHead(HashCodeFcn(key));
HashEntry<Key, Value> * pEntry = *ppHashEntryListHead;
while (pEntry != 0)
{
if (EqualKey(pEntry->key, key))
return pEntry;
pEntry = pEntry->_next;
}
return 0;
}
template <typename Key, typename Value, int _hashTableSize, unsigned long (*HashCodeFcn)(Key key), bool (*EqualKey)(Key key1, Key key2)>
void SimpleHashTable<Key, Value, _hashTableSize, HashCodeFcn, EqualKey>::Foreach(bool (*VisitorFunc)(Key key, Value value))
{
for (int i = 0; i < _hashTableSize; i++)
{
HashEntry<Key, Value> * pEntry = this->hashBucket[i];
while(pEntry != 0)
{
bool continueLoop = VisitorFunc(pEntry->key, pEntry->value);
if (! continueLoop)
break;
pEntry = pEntry->_next;
}
}
}

Просмотреть файл

@ -0,0 +1,3 @@
#include "ILog.h"
ILog::~ILog() {}

Просмотреть файл

@ -0,0 +1,15 @@
#pragma once
#include <wchar.h>
class ILog
{
public:
virtual bool AddRecord(const char * logMsg) = 0;
virtual char * Record(int index) = 0;
virtual int RecordCount() = 0;
virtual ~ILog() = 0;
virtual bool Export(const wchar_t * filename) = 0;
virtual void ClearData() = 0;
};

Просмотреть файл

@ -0,0 +1,336 @@
#include <Windows.h>
#include <string>
#include <algorithm>
#include <sstream>
#include <memory>
#include "LogWithFileBackup.h"
using namespace std;
int LogWithBackUpFile::index = 0;
SpinLock LogWithBackUpFile::__lockFile;
LogWithBackUpFile * LogWithBackUpFile::Make(const char * folder, const char * name)
{
LogWithBackUpFile * logObj = new LogWithBackUpFile();
__lockFile.Lock();
HRESULT hr = logObj->CreateFile(folder, name);
__lockFile.Unlock();
if (SUCCEEDED(hr))
return logObj;
else
{
delete logObj;
return nullptr;
}
}
LogWithBackUpFile::LogWithBackUpFile() :
logfileW(INVALID_HANDLE_VALUE),
logfileR(INVALID_HANDLE_VALUE),
idxfileW(INVALID_HANDLE_VALUE),
idxfileR(INVALID_HANDLE_VALUE),
recordCount(0),
_bFileIsFull(false)
{
}
LogWithBackUpFile::~LogWithBackUpFile()
{
SafeCloseHandles();
}
HRESULT LogWithBackUpFile::CreateFile(const char * folder, const char * name)
{
do {
this->foldername = folder;
if (!CreateDirectoryRecursive(this->foldername.c_str()))
break;
ostringstream os;
os << folder << "\\" << name << ".txt";
this->logfileName = os.str();
ostringstream os2;
os2 << folder << "\\" << name << ".idx";
this->idxfileName = os2.str();
auto CreateForAppend = [](const string & name){
return CreateFileA(
name.c_str(),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
};
logfileW = CreateForAppend(this->logfileName);
if (logfileW == INVALID_HANDLE_VALUE)
break;
idxfileW = CreateForAppend(this->idxfileName);
if (idxfileW == INVALID_HANDLE_VALUE)
break;
auto OpenForReadIfExist = [](const string & name){
return CreateFileA(
name.c_str(),
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
};
logfileR = OpenForReadIfExist(this->logfileName);
if (logfileR == INVALID_HANDLE_VALUE)
break;
idxfileR = OpenForReadIfExist(this->idxfileName);
if (idxfileR == INVALID_HANDLE_VALUE)
break;
return 0;
} while(0);
SafeCloseHandles();
return -1;
}
bool LogWithBackUpFile::AddRecord(const char * logMsg)
{
if (_bFileIsFull)
{
return false;
}
if (this->logfileW == INVALID_HANDLE_VALUE)
return false;
if (this->idxfileW == INVALID_HANDLE_VALUE)
return false;
bool bFileIsFull = false;
int lenLogMsg = strlen(logMsg);
int logFileSize = GetFileSize(this->logfileW, NULL);
int indexFileSize = GetFileSize(this->idxfileW, NULL);
const int FILE_SIZE_LIMIT = INT_MAX;
if ( (((__int64)logFileSize + lenLogMsg) > FILE_SIZE_LIMIT) ||
((__int64)indexFileSize + sizeof(IdxRecord)) > FILE_SIZE_LIMIT)
{
bFileIsFull = true;
}
else do {
DWORD numWritten = 0;
::SetFilePointer(this->logfileW, 0, 0, 2);
::WriteFile(this->logfileW, logMsg, lenLogMsg, &numWritten, NULL);
if (numWritten < lenLogMsg) // log file is full
{
bFileIsFull = true;
break;
}
IdxRecord idxRecord;
idxRecord.offset = logFileSize;
idxRecord.length = lenLogMsg;
::SetFilePointer(this->idxfileW, 0, 0, 2);
::WriteFile(this->idxfileW, &idxRecord, sizeof(idxRecord), &numWritten, NULL);
if (numWritten < sizeof(idxRecord))
{
bFileIsFull = true;
break;
}
++recordCount;
} while(0);
if (bFileIsFull)
{
_bFileIsFull = true;
++recordCount; // for the last error message
return false;
}
return true;
}
char * LogWithBackUpFile::Record(int index)
{
if (_bFileIsFull)
{
if (index == recordCount - 1)
{
return strdup("Error: log buffer is full\n");
}
}
if (this->logfileR == INVALID_HANDLE_VALUE)
return 0;
if (this->idxfileR == INVALID_HANDLE_VALUE)
return 0;
if (index >= recordCount)
return 0;
IdxRecord idxRecord;
DWORD numRead;
if (::SetFilePointer(this->idxfileR, index*sizeof(IdxRecord), 0, 0) == INVALID_SET_FILE_POINTER)
return 0;
BOOL bSucc = ::ReadFile(this->idxfileR, &idxRecord, sizeof(IdxRecord), &numRead, NULL);
if (!bSucc)
return 0;
if (::SetFilePointer(this->logfileR, idxRecord.offset, 0, 0) == INVALID_SET_FILE_POINTER)
return 0;
char * readBuf = new char[idxRecord.length+1];
readBuf[idxRecord.length] = 0;
bSucc = ::ReadFile(this->logfileR, readBuf, idxRecord.length, &numRead, NULL);
if (bSucc)
return readBuf;
else
{
delete [] readBuf;
return 0;
}
}
int LogWithBackUpFile::RecordCount()
{
return recordCount;
}
void LogWithBackUpFile::SafeCloseHandles()
{
auto SafeCloseHandle = [](HANDLE& handle){
if (handle != INVALID_HANDLE_VALUE)
{
CloseHandle(handle);
handle = INVALID_HANDLE_VALUE;
}
};
SafeCloseHandle(logfileW);
SafeCloseHandle(logfileR);
SafeCloseHandle(idxfileW);
SafeCloseHandle(idxfileR);
}
bool LogWithBackUpFile::CreateDirectoryRecursive(const char * __folder)
{
bool bSucc;
char * folderDup = _strdup(__folder);
int strlength = strlen(folderDup);
// remove the last '\'
if ( *(folderDup + strlength - 1) == '\\' )
folderDup[strlength - 1] = 0;
char * ptr = (char *)(folderDup + strlength - 1);
while(ptr > folderDup && *ptr != '\\')
--ptr;
if (ptr == folderDup) // root
bSucc = true;
else
{
*ptr = 0;
bSucc = CreateDirectoryRecursive(folderDup);
if (bSucc)
{
*ptr = '\\';
BOOL bRes = CreateDirectoryA(folderDup, NULL);
if (!bRes && GetLastError() != ERROR_ALREADY_EXISTS)
bSucc = false;
bSucc = true;
}
else
bSucc = false;
}
delete [] folderDup;
return bSucc;
}
bool LogWithBackUpFile::Export(const wchar_t * filename)
{
auto hfileOutput = ::CreateFileW(
filename,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (hfileOutput == INVALID_HANDLE_VALUE)
return false;
const int MAX_COUNT = 1*1024*1024;
std::unique_ptr<char []> readBuf(new char[MAX_COUNT]);
DWORD numRead;
DWORD numWrite;
int offset = 0;
do {
::SetFilePointer(this->logfileR, offset, 0, 0);
BOOL bSucc = ::ReadFile(this->logfileR, readBuf.get(), MAX_COUNT, &numRead, NULL);
if (bSucc == FALSE)
break;
if (numRead == 0)
break;
::SetFilePointer(hfileOutput, 0, 0, 2);
bSucc = ::WriteFile(hfileOutput, readBuf.get(), numRead, &numWrite, NULL);
if (bSucc == FALSE)
break;
if (numRead < MAX_COUNT || numWrite < numRead)
break;
offset += MAX_COUNT;
} while(1);
CloseHandle(hfileOutput);
return true;
}
void LogWithBackUpFile::ClearData()
{
auto ResetFile = [](HANDLE hFile){
::SetFilePointer(hFile, 0, 0, 0);
::SetEndOfFile(hFile);
};
ResetFile(this->idxfileR);
ResetFile(this->idxfileW);
ResetFile(this->logfileR);
ResetFile(this->logfileW);
this->recordCount = 0;
this->_bFileIsFull = false;
}

Просмотреть файл

@ -0,0 +1,56 @@
#pragma once
#include <string>
#include <Windows.h>
#include "ILog.h"
#include "SpinLock.h"
class LogWithBackUpFile : public ILog
{
public:
// Factory
static LogWithBackUpFile * __stdcall Make(const char * folder, const char * name);
static SpinLock __lockFile;
public:
struct IdxRecord
{
int offset;
int length;
};
// ILog interface
bool AddRecord(const char * logMsg);
char * Record(int index);
int RecordCount();
~LogWithBackUpFile();
private:
static int index;
private:
LogWithBackUpFile();
HRESULT CreateFile(const char * folder, const char * name);
void SafeCloseHandles();
bool CreateDirectoryRecursive(const char * folder);
std::string foldername;
std::string logfileName;
std::string idxfileName;
HANDLE logfileW;
HANDLE idxfileW;
HANDLE logfileR;
HANDLE idxfileR;
int recordCount;
bool _bFileIsFull;
public:
virtual bool Export(const wchar_t * filename);
virtual void ClearData();
};

Просмотреть файл

@ -0,0 +1,58 @@
#include "PathName.h"
const wchar_t * PathName::__reserved_char = L"\\/:*?\"<>| ";
PathName::PathName()
{
}
void PathName::AppendWithEscape(const wchar_t * name, wchar_t creplace)
{
const wchar_t * ptr = name;
wchar_t c;
while( (c = *ptr) != 0 )
{
if (IsReserved(c))
c = creplace;
_path.push_back(c);
++ptr;
}
}
void PathName::Append(const wchar_t * name)
{
const wchar_t * ptr = name;
wchar_t c;
while( (c = *ptr) != 0 )
{
_path.push_back(c);
++ptr;
}
}
void PathName::Reset()
{
_path.clear();
}
PathName::operator const wchar_t *()
{
if ( (_path.size() == 0) ||
_path[_path.size()-1] != 0
)
{
_path.push_back(0);
}
return &_path[0];
}
bool PathName::IsReserved(wchar_t c)
{
for (auto ptr = __reserved_char; *ptr != 0; ++ptr)
{
if (*ptr == c)
return true;
}
return false;
}

Просмотреть файл

@ -0,0 +1,25 @@
#pragma once
#include <Windows.h>
#include <vector>
class PathName
{
public:
PathName();
void AppendWithEscape(const wchar_t * name, wchar_t creplace);
void Append(const wchar_t * name);
void Reset();
operator const wchar_t *();
private:
bool IsReserved(wchar_t c);
private:
static const wchar_t * __reserved_char;
std::vector<wchar_t> _path;
};

Просмотреть файл

@ -0,0 +1,136 @@
#pragma once
#include <assert.h>
#include <functional>
#include <list>
#include "ReadWriteLock.h"
#if 0
namespace SoraDbgPlot { namespace Task {
class RWTaskQueue
{
public:
typedef std::function<void(void)> TaskFunc;
private:
enum TaskType
{
TYPE_READ,
TYPE_WRITE,
};
struct Task
{
TaskType _type;
TaskFunc _func;
};
public:
RWTaskQueue()
{
_exeToken = 0;
_activeCount = 0;
}
~RWTaskQueue()
{
while(1)
{
bool bBreak = false;
_lockList.Lock();
if (_taskList.size() == 0)
bBreak = true;
_lockList.Unlock();
if (bBreak) break;
}
}
void DoTaskWrite(const TaskFunc & f)
{
::InterlockedIncrement(&_activeCount);
_lockRunning.LockWrite();
f();
_lockRunning.UnlockWrite();
if (::InterlockedDecrement(&_activeCount) == 0)
ExecuteTaskAsync(false);
}
void QueueTaskRead();
void QueueTaskWrite();
private:
void ExecuteTaskAsync(bool doPop)
{
std::list<TaskFunc *> _newTaskList;
_lockList.Lock();
if (doPop)
{
_exeToken = false;
}
if (_exeToken == false)
{
if (_taskList.size() > 0)
{
_exeToken = true;
}
}
_lockList.Unlock();
while(_newTaskList.si
if (_newTaskList.size() > 0)
{
BOOL succ = QueueUserWorkItem(ThreadExecuteTask, this, WT_EXECUTEDEFAULT);
assert(succ != 0);
}
}
static DWORD WINAPI ThreadExecuteTask(__in LPVOID lpParameter)
{
auto queue = (TaskQueue *)lpParameter;
//::InterlockedIncrement(&queue->_activeCnt);
queue->_lockRunning.Lock();
queue->_task();
queue->_lockRunning.Unlock();
//queue->_lockList.Lock();
//queue->_taskList.pop_front();
//queue->_lockList.Unlock();
//if (::InterlockedDecrement(&queue->_activeCnt) == 0)
queue->ExecuteTaskAsync(true);
return 0;
}
private:
TaskFunc _task;
std::list<Task> _taskList;
SoraDbgPlot::Lock::RWLock _lockRunning;
SoraDbgPlot::Lock::CSLock _lockList;
//SoraDbgPlot::Lock::CSRecursiveLock _lockRunning;
//SoraDbgPlot::Lock::CSLock _lockList;
//HANDLE _evenTaskComplete;
//volatile unsigned long _activeCnt;
volatile unsigned long _exeToken;
volatile unsigned long _activeCount;
TaskType _taskType;
};
}}
#endif

Просмотреть файл

@ -0,0 +1,29 @@
========================================================================
STATIC LIBRARY : Common Project Overview
========================================================================
AppWizard has created this Common library project for you.
No source files were created as part of your project.
Common.vcxproj
This is the main project file for VC++ projects generated using an Application Wizard.
It contains information about the version of Visual C++ that generated the file, and
information about the platforms, configurations, and project features selected with the
Application Wizard.
Common.vcxproj.filters
This is the filters file for VC++ projects generated using an Application Wizard.
It contains information about the association between the files in your project
and the filters. This association is used in the IDE to show grouping of files with
similar extensions under a specific node (for e.g. ".cpp" files are associated with the
"Source Files" filter).
/////////////////////////////////////////////////////////////////////////////
Other notes:
AppWizard uses "TODO:" comments to indicate parts of the source code you
should add to or customize.
/////////////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -0,0 +1,52 @@
#pragma once
#include "CSRecursiveLock.h"
namespace SoraDbgPlot { namespace Lock {
class RWLock
{
public:
RWLock()
{
_readCount = 0;
}
~RWLock()
{
}
void LockWrite()
{
_wlock.Lock();
}
void UnlockWrite()
{
_wlock.Unlock();
}
void LockRead()
{
_rlock.Lock();
_readCount++;
if (_readCount == 1)
_wlock.Lock();
_rlock.Unlock();
}
void UnlockRead()
{
_rlock.Lock();
_readCount--;
if (_readCount == 0)
_wlock.Unlock();
_rlock.Unlock();
}
private:
SoraDbgPlot::Lock::CSLock _rlock;
SoraDbgPlot::Lock::CSLock _wlock;
int _readCount;
};
}}

Просмотреть файл

@ -0,0 +1,165 @@
#pragma once
#include <Windows.h>
#include <exception>
#include <functional>
template <typename T>
class RingBuffer
{
public:
RingBuffer(size_t count);
~RingBuffer();
size_t Write(const T * ptr, size_t count);
bool Read(size_t start, size_t len, T * addr, size_t maxLen, size_t & sizeRead);
T operator[](size_t index);
size_t Size();
size_t Capacity();
size_t WriteIndex();
void Reset();
typedef std::function<void(const T *, size_t)> ExportFunc;
bool Export(const ExportFunc &);
bool ExportRange(size_t start, size_t length, const ExportFunc &);
private:
T * _buffer;
T * _pWrite;
size_t _dataCount;
size_t _maxCount;
};
template <typename T>
RingBuffer<T>::RingBuffer(size_t count) {
_maxCount = count;
_buffer = new T[_maxCount];
_pWrite = _buffer;
_dataCount = 0;
}
template <typename T>
RingBuffer<T>::~RingBuffer()
{
delete [] _buffer;
}
template <typename T>
size_t RingBuffer<T>::Write(const T * ptr, size_t count)
{
if (count <= 0)
return 0;
size_t cntToWrite = min(count, _maxCount);
_dataCount = min(_dataCount + cntToWrite, _maxCount);
size_t retCnt = cntToWrite;
size_t cntToBufEnd = _buffer + _maxCount - _pWrite;
size_t count1 = min(cntToBufEnd, cntToWrite);
memcpy(_pWrite, ptr, count1 * sizeof(T));
cntToWrite -= count1;
_pWrite += count1;
if (_pWrite == _buffer + _maxCount)
_pWrite = _buffer;
if (cntToWrite > 0)
{
ptr = ptr + count1;
memcpy(_pWrite, ptr, cntToWrite * sizeof(T));
_pWrite += cntToWrite;
}
return retCnt;
}
template <typename T>
bool RingBuffer<T>::Read(size_t start, size_t len, T * addr, size_t maxLen, size_t & sizeRead)
{
size_t sizeToRead = min(maxLen, len);
sizeRead = sizeToRead;
size_t s1 = (_maxCount - start);
s1 = min(s1, len);
memcpy(addr, _buffer + start, sizeof(T) * s1);
addr += s1;
sizeToRead -= s1;
if (sizeToRead > 0)
{
size_t s2 = sizeToRead;
memcpy(addr, _buffer, sizeof(T) * s2);
}
return true;
}
template <typename T>
T RingBuffer<T>::operator[](size_t index) {
if (index < 0 || index >= _dataCount)
throw std::exception("index out of range");
T * ptr = _pWrite - 1 - index;
if (ptr < _buffer)
ptr += _maxCount;
return *ptr;
}
template <typename T>
size_t RingBuffer<T>::Size()
{
return _dataCount;
}
template <typename T>
size_t RingBuffer<T>::Capacity()
{
return _maxCount;
}
template <typename T>
size_t RingBuffer<T>::WriteIndex()
{
return _pWrite - _buffer;
}
template <typename T>
void RingBuffer<T>::Reset()
{
_pWrite = _buffer;
_dataCount = 0;
}
template <typename T>
bool RingBuffer<T>::Export(const ExportFunc & f)
{
return ExportRange(0, _dataCount, f);
}
template <typename T>
bool RingBuffer<T>::ExportRange(size_t start, size_t length, const ExportFunc & f)
{
int lengthToProcess = length;
if (lengthToProcess <= 0)
return false;
int indexStart = _pWrite - _buffer - start - lengthToProcess;
if (indexStart < 0)
{
indexStart += _maxCount;
int length1 = _maxCount - indexStart; // till end of buffer
f(_buffer + indexStart, length1);
indexStart += length1;
indexStart = indexStart % _maxCount;
lengthToProcess -= length1;
}
if (lengthToProcess <= 0)
return true;
f(_buffer + indexStart, lengthToProcess);
return true;
}

Просмотреть файл

@ -0,0 +1,144 @@
#pragma once
#include <functional>
#include "RingBuffer.h"
#include "TimeStampQueue.h"
template <typename T>
class RingBufferWithTimeStamp
{
public:
RingBufferWithTimeStamp(size_t size);
~RingBufferWithTimeStamp();
size_t Write(const T * ptr, size_t count, unsigned long long timeStamp);
bool GetTimeStampBySample(size_t index, unsigned long long & timestamp);
bool GetNearestOldTimeStamp(unsigned long long in, unsigned long long & out, size_t & outIdx);
size_t Size();
size_t RecordCount();
bool GetDataSizeByTimeStampIdx(size_t idx, size_t & out);
bool ReadDataByTimeStampIdx(size_t idx, T * addr, size_t maxLen, size_t & sizeRead);
T operator[] (size_t index);
void Reset();
typedef std::function<void(const T *, size_t)> ExportFunc;
bool Export(const ExportFunc &);
bool ExportRange(size_t start, size_t length, const ExportFunc &);
private:
RingBuffer<T> * _ringBuffer;
TimeStampQueue * _timeStampQueue;
};
template <typename T>
RingBufferWithTimeStamp<T>::RingBufferWithTimeStamp(size_t size)
{
_ringBuffer = new RingBuffer<T>(size);
_timeStampQueue = new TimeStampQueue(size);
}
template <typename T>
RingBufferWithTimeStamp<T>::~RingBufferWithTimeStamp()
{
delete _ringBuffer;
delete _timeStampQueue;
}
template <typename T>
size_t RingBufferWithTimeStamp<T>::Write(const T * ptr, size_t count, unsigned long long timeStamp)
{
if (count < 0)
return 0;
size_t writeIdx1 = _ringBuffer->WriteIndex();
size_t cntWritten = _ringBuffer->Write(ptr, count);
size_t writeIdx2 = _ringBuffer->WriteIndex();
DataRecord record;
record._start = writeIdx1;
record._size = (writeIdx2 - writeIdx1) % _ringBuffer->Capacity();
record._timestamp = timeStamp;
_timeStampQueue->AddRecord(record);
return cntWritten;
}
template <typename T>
bool RingBufferWithTimeStamp<T>::GetTimeStampBySample(size_t index, unsigned long long & timestamp)
{
size_t targetIndex = (_ringBuffer->WriteIndex() - 1 - index) % _ringBuffer->Capacity();
return _timeStampQueue->Search(targetIndex, timestamp);
}
template <typename T>
bool RingBufferWithTimeStamp<T>::GetNearestOldTimeStamp(unsigned long long timestamp, unsigned long long & out, size_t & outIdx)
{
return _timeStampQueue->SearchNearestTimeStamp(timestamp, out, outIdx);
}
template <typename T>
size_t RingBufferWithTimeStamp<T>::Size()
{
return _ringBuffer->Size();
}
template <typename T>
size_t RingBufferWithTimeStamp<T>::RecordCount()
{
return _timeStampQueue->Size();
}
template <typename T>
T RingBufferWithTimeStamp<T>::operator[] (size_t index)
{
return (*_ringBuffer)[index];
}
template <typename T>
void RingBufferWithTimeStamp<T>::Reset()
{
_ringBuffer->Reset();
_timeStampQueue->Reset();
}
template <typename T>
bool RingBufferWithTimeStamp<T>::GetDataSizeByTimeStampIdx(size_t idx, size_t & out)
{
DataRecord record;
bool found = _timeStampQueue->GetDataRecord(idx, record);
if (found)
{
out = record._size;
return true;
}
return false;
}
template <typename T>
bool RingBufferWithTimeStamp<T>::ReadDataByTimeStampIdx(size_t idx, T * addr, size_t maxLen, size_t & sizeRead)
{
DataRecord record;
bool found = _timeStampQueue->GetDataRecord(idx, record);
if (!found)
{
return false;
}
return this->_ringBuffer->Read(record._start, record._size, addr, maxLen, sizeRead);
}
template <typename T>
bool RingBufferWithTimeStamp<T>::Export(const ExportFunc & f)
{
return _ringBuffer->Export(f);
}
template <typename T>
bool RingBufferWithTimeStamp<T>::ExportRange(size_t start, size_t length, const ExportFunc & f)
{
return _ringBuffer->ExportRange(start, length, f);
}

Просмотреть файл

@ -0,0 +1,15 @@
#pragma once
#include <memory>
namespace SoraDbgPlot { namespace Task {
class Runnable : public std::enable_shared_from_this<Runnable>
{
public:
virtual void Run() = 0;
virtual std::shared_ptr<Runnable> ContinueWith(std::shared_ptr<Runnable>) = 0;
virtual ~Runnable() {}
};
}}

Просмотреть файл

@ -0,0 +1,46 @@
#pragma once
#include <Windows.h>
#include <assert.h>
#include "_share_mem_if.h"
#include "_share_lock_if.h"
#include "DACL_Control.h"
static inline ShareLock * AllocateSharedEvent(
BOOL bManualReset,
BOOL bInitialState,
LPCWSTR lpName)
{
ShareLock * lock = NULL;
SECURITY_ATTRIBUTES sa;
CreateDACLWithAllAccess(&sa);
lock = ShareLock::AllocateShareEvent(&sa, bManualReset, bInitialState, lpName);
LocalFree(sa.lpSecurityDescriptor);
return lock;
}
static inline ShareMem * AllocateSharedMem(const wchar_t * name, int size, ShareMemClassInit * initFunc, void * context = 0)
{
ShareMem * sm = NULL;
SECURITY_ATTRIBUTES sa;
BOOL succ = CreateDACLWithAllAccess(&sa);
sm = ShareMem::AllocateShareMem(
INVALID_HANDLE_VALUE,
&sa,
PAGE_READWRITE,
size,
name,
FILE_MAP_ALL_ACCESS,
initFunc,
context
);
LocalFree(sa.lpSecurityDescriptor);
return sm;
}
static inline BOOL DummyShareMemClassInit(ShareMem* sm, void* context)
{ return TRUE; } // do nothing
#ifdef ASSERT
#undef ASSERT
#endif

Просмотреть файл

@ -0,0 +1,42 @@
#pragma once
#include <Windows.h>
#include <assert.h>
//#include "_share_mem_if.h"
#include "ShareMemHelper.h"
namespace SoraDbgPlot { namespace Common
{
class SharedSerialNumGenerator
{
public:
SharedSerialNumGenerator(const wchar_t * sharedName)
{
_sm = AllocateSharedMem(
sharedName,
4,
SharedMemInit,
0);
}
~SharedSerialNumGenerator()
{
ShareMem::FreeShareMem(_sm);
}
unsigned int GetSerialNum()
{
volatile unsigned int * addr = (unsigned int *)_sm->GetAddress();
return ::InterlockedIncrement(addr);
}
static BOOL SharedMemInit(ShareMem* sm, void* context)
{
int * addr = (int *)sm->GetAddress();
*addr = 0;
return TRUE;
}
ShareMem * _sm;
};
}}

Просмотреть файл

@ -0,0 +1,66 @@
#pragma once
#include <stdio.h>
#include <string.h>
template <typename ValueType>
class SimpleVector
{
public:
SimpleVector();
~SimpleVector();
void Append(ValueType value);
void Foreach(bool (*VisitorFunc)(int index, ValueType value));
private:
void Realloc();
static const int DEFAULT_SIZE = 64;
ValueType * _buffer;
int _size;
int _index;
};
template <typename ValueType>
SimpleVector<ValueType>::SimpleVector()
{
_size = DEFAULT_SIZE;
_buffer = new ValueType[_size];
_index = 0;
}
template <typename ValueType>
SimpleVector<ValueType>::~SimpleVector()
{
delete [] _buffer;
}
template <typename ValueType>
void SimpleVector<ValueType>::Append(ValueType value)
{
if (_index == _size)
Realloc();
_buffer[_index++] = value;
}
template <typename ValueType>
void SimpleVector<ValueType>::Realloc()
{
_size *= 2;
ValueType * newBuf = new ValueType[_size];
if (_index > 0)
memcpy(newBuf, _buffer, _index*sizeof(ValueType));
delete [] _buffer;
_buffer = newBuf;
}
template <typename ValueType>
void SimpleVector<ValueType>::Foreach(bool (*VisitorFunc)(int index, ValueType value))
{
for (int i = 0; i < _index; i++)
{
bool continueLoop = VisitorFunc(i, _buffer[i]);
if (!continueLoop)
break;
}
}

Просмотреть файл

@ -0,0 +1,19 @@
#pragma once
#include <Windows.h>
class SpinLock
{
public:
SpinLock() {
value = 0;
}
void Lock() {
while(::InterlockedCompareExchange(&value, 1, 0) != 0);
}
void Unlock() {
InterlockedExchange(&value, 0);
}
private:
volatile LONG value;
};

Просмотреть файл

@ -0,0 +1,59 @@
#pragma once
#include <map>
#include <algorithm>
#include <functional>
#include <memory>
#include <Windows.h>
#include "CSRecursiveLock.h"
namespace SoraDbgPlot { namespace Strategy {
template <typename T, typename R>
class Strategy
{
typedef std::function<void(const void *, const T &, R &)> CallbackType;
public:
void Set(const CallbackType & f) {
_lock.Lock();
_callback.reset();
_callback = std::make_shared<CallbackType>(f);
_lock.Unlock();
}
void UnSet() {
_lock.Lock();
_callback.reset();
_lock.Unlock();
}
bool Call(const void * sender, const T & e, R & r) {
bool ret = false;
_lock.Lock();
if (_callback.get())
{
(*_callback)(sender, e, r);
ret = true;
}
_lock.Unlock();
return ret;
}
void Reset()
{
_lock.Lock();
_callback.reset();
_lock.Unlock();
}
private:
std::shared_ptr<CallbackType > _callback;
SoraDbgPlot::Lock::CSRecursiveLock _lock;
};
}}

Просмотреть файл

@ -0,0 +1,83 @@
#pragma once
#include <memory>
#include <list>
#include <assert.h>
#include "Runnable.h"
#include "TaskSimple.h"
namespace SoraDbgPlot { namespace Task {
class TaskCoordinator : public Runnable
{
public:
TaskCoordinator(std::shared_ptr<SoraDbgPlot::Task::TaskQueue> queue)
{
_taskQueue = queue;
}
~TaskCoordinator()
{
int debug = 10;
}
void AddTask(std::shared_ptr<TaskSimple> t)
{
_taskList.push_back(t);
}
void AddTask(std::shared_ptr<TaskSimple> t[], int count)
{
for (int i = 0; i < count; i++)
{
_taskList.push_back(t[i]);
}
}
void Run()
{
if (_taskList.size() == 0)
_runnableContinue->Run();
auto shared_me = std::dynamic_pointer_cast<TaskCoordinator, Runnable>(shared_from_this());
_remainCount = 0;
std::for_each(_taskList.begin(), _taskList.end(), [shared_me](std::shared_ptr<TaskSimple> task){
shared_me -> _remainCount++;
auto shared_me_2 = shared_me;
task->ContinueWith(std::make_shared<SoraDbgPlot::Task::TaskSimple>(shared_me_2->_taskQueue, [shared_me_2](){
if (::InterlockedDecrement(&shared_me_2->_remainCount) == 0)
{
if (shared_me_2->_runnableContinue)
shared_me_2->_runnableContinue->Run();
shared_me_2->_taskList.clear();
}
}));
task->Run();
});
}
virtual std::shared_ptr<Runnable> ContinueWith(std::shared_ptr<Runnable> t)
{
if (_runnableContinue)
return _runnableContinue->ContinueWith(t);
else
{
_runnableContinue = t;
return t;
}
}
private:
TaskCoordinator(const TaskCoordinator &) {}
TaskCoordinator(TaskCoordinator &&) {}
private:
std::shared_ptr<Runnable> _runnableContinue;
std::list<std::shared_ptr<TaskSimple> > _taskList;
volatile unsigned long _remainCount;
std::shared_ptr<SoraDbgPlot::Task::TaskQueue> _taskQueue;
};
}}

Просмотреть файл

@ -0,0 +1,18 @@
#include <Windows.h>
#include "TaskQueue.h"
using namespace SoraDbgPlot::Task;
volatile unsigned long SoraDbgPlot::Task::TaskQueue::__countQueue = 0;
HANDLE SoraDbgPlot::Task::TaskQueue::__eventWait = ::CreateEvent(NULL, FALSE, TRUE, NULL);
volatile bool SoraDbgPlot::Task::TaskQueue::__clean = false;
#ifdef _DEBUG
volatile unsigned long SoraDbgPlot::Task::TaskQueue::__taskCntInQueue = 0;
volatile unsigned long SoraDbgPlot::Task::TaskQueue::__taskCntToRun = 0;
volatile unsigned long SoraDbgPlot::Task::TaskQueue::__taskCntRunning = 0;
volatile unsigned long SoraDbgPlot::Task::TaskQueue::__taskQueueOpCount = 0;
#endif
volatile unsigned long SoraDbgPlot::Task::TaskQueue::__sid = 0;
volatile unsigned long SoraDbgPlot::Task::TaskQueue::__taskNum = 0;

Просмотреть файл

@ -0,0 +1,266 @@
#pragma once
#include <functional>
#include <list>
#include <memory>
#include <assert.h>
#include "CSLock.h"
#include "CSRecursiveLock.h"
#include "ReadWriteLock.h"
namespace SoraDbgPlot { namespace Task {
class TaskQueue : public std::enable_shared_from_this<TaskQueue>
{
public:
typedef std::function<void(void)> TaskFunc;
TaskQueue()
{
::InterlockedIncrement(&TaskQueue::__countQueue);
_exeToken = TASK_TOKEN_NOT_TAKEN;
}
private:
TaskQueue(const TaskQueue &) {}
TaskQueue(TaskQueue &&) {}
public:
~TaskQueue()
{
::SetEvent(TaskQueue::__eventWait);
::InterlockedDecrement(&TaskQueue::__countQueue);
}
void DoTask(const TaskFunc & f)
{
_lockRunning.Lock();
f();
_lockRunning.Unlock();
ExecuteTaskAsync();
}
void QueueTask(const TaskFunc & f)
{
#ifdef _DEBUG
::InterlockedIncrement(&__taskQueueOpCount);
#endif
::InterlockedIncrement(&__taskNum);
::InterlockedIncrement(&__sid);
TaskStruct taskStruct;
taskStruct._func = f;
taskStruct._doClean = false;
_lockList.Lock();
_taskList.push_back(taskStruct);
#ifdef _DEBUG
::InterlockedIncrement(&__taskCntInQueue);
#endif
_lockList.Unlock();
ExecuteTaskAsync();
#ifdef _DEBUG
::InterlockedDecrement(&__taskQueueOpCount);
#endif
}
void QueueTask(const TaskFunc & f, const TaskFunc & cleanFunc)
{
::InterlockedIncrement(&__taskNum);
::InterlockedIncrement(&__sid);
TaskStruct taskStruct;
taskStruct._func = f;
taskStruct._cleanFunc = cleanFunc;
taskStruct._doClean = true;
_lockList.Lock();
_taskList.push_back(taskStruct);
#ifdef _DEBUG
::InterlockedIncrement(&__taskCntInQueue);
#endif
_lockList.Unlock();
ExecuteTaskAsync();
}
private:
static DWORD WINAPI ThreadExecuteTask(__in LPVOID lpParameter)
{
#ifdef _DEBUG
::InterlockedIncrement(&__taskCntRunning);
::InterlockedDecrement(&__taskCntToRun);
#endif
auto queue = (TaskQueue *)lpParameter;
auto SThis = queue->_me;
queue->_lockRunning.Lock();
if (!__clean)
{
queue->_task._func();
}
else
{
if (queue->_task._doClean)
queue->_task._cleanFunc();
}
queue->_lockRunning.Unlock();
queue->_task._func = [](){};
queue->_task._cleanFunc = [](){};
queue->_task._doClean = false;
queue->_me.reset();
queue->_lockList.Lock();
queue->_exeToken = TASK_TOKEN_NOT_TAKEN;
queue->_lockList.Unlock();
queue->ExecuteTaskAsync();
#ifdef _DEBUG
::InterlockedDecrement(&__taskCntRunning);
#endif
::InterlockedDecrement(&__taskNum);
return 0;
}
void ExecuteTaskAsync()
{
bool takeATask = false;
_lockList.Lock();
if (_exeToken == TASK_TOKEN_NOT_TAKEN)
{
if (_taskList.size() > 0)
{
_task = _taskList.front();
_taskList.pop_front();
#ifdef _DEBUG
::InterlockedDecrement(&__taskCntInQueue);
#endif
_exeToken = TASK_TOKEN_TAKEN;
_me = shared_from_this();
takeATask = true;
}
}
_lockList.Unlock();
if (takeATask)
{
BOOL succ = QueueUserWorkItem(ThreadExecuteTask, this, WT_EXECUTEDEFAULT);
if (succ != 0)
{
#ifdef _DEBUG
::InterlockedIncrement(&__taskCntToRun);
#endif
}
else
{
assert(false);
}
}
}
struct TaskStruct
{
TaskFunc _func;
TaskFunc _cleanFunc;
bool _doClean;
};
TaskStruct _task;
std::list<TaskStruct> _taskList;
SoraDbgPlot::Lock::CSLock _lockRunning;
SoraDbgPlot::Lock::CSLock _lockList;
volatile unsigned long _exeToken;
std::shared_ptr<TaskQueue> _me;
enum {
TASK_TOKEN_TAKEN,
TASK_TOKEN_NOT_TAKEN
};
// resource management
public:
static int __stdcall WaitAndClean(DWORD time)
{
__clean = true;
while(1)
{
::WaitForSingleObject(__eventWait, time);
int activeCount = __countQueue;
if (activeCount == 0)
{
::CloseHandle(__eventWait);
}
return activeCount;
}
}
#ifdef _DEBUG
static unsigned long MonitorQueueNum()
{
return __countQueue;
}
static unsigned long MonitorTaskInQueue()
{
return __taskCntInQueue;
}
static unsigned long MonitorTaskCntToRun()
{
return __taskCntToRun;
}
static unsigned long MonitorTaskCntRunning()
{
return __taskCntRunning;
}
static unsigned long MonitorTaskQueueOpCnt()
{
return __taskQueueOpCount;
}
#endif
static unsigned long Sid()
{
return __sid;
}
static unsigned long RemainingTask()
{
return __taskNum;
}
private:
#ifdef _DEBUG
static volatile unsigned long __taskCntInQueue;
static volatile unsigned long __taskCntToRun;
static volatile unsigned long __taskCntRunning;
static volatile unsigned long __taskQueueOpCount;
#endif
static HANDLE __eventWait;
static volatile unsigned long __countQueue;
static volatile bool __clean;
static volatile unsigned long __sid;
static volatile unsigned long __taskNum;
};
}}

Просмотреть файл

@ -0,0 +1,20 @@
#pragma once
#if 0
namespace SoraDbgPlot { namespace Task {
class TaskQueueRequester
{
public:
TaskQueueRequester(size_t size)
{
_maxSize = size;
}
private:
size_t _maxSize;
};
}}
#endif

Просмотреть файл

@ -0,0 +1,71 @@
#pragma once
#include <assert.h>
#include <memory>
#include <algorithm>
#include "TaskQueue.h"
#include "Runnable.h"
namespace SoraDbgPlot { namespace Task
{
class TaskSimple : public Runnable
{
public:
TaskSimple(std::shared_ptr<TaskQueue> queue, const TaskQueue::TaskFunc & f)
{
_func = f;
_dtor = [](){};
_taskQueue = queue;
}
TaskSimple(std::shared_ptr<TaskQueue> queue, const TaskQueue::TaskFunc & f, const TaskQueue::TaskFunc & dtor)
{
_func = f;
_dtor = dtor;
_taskQueue = queue;
}
~TaskSimple()
{
;
}
std::shared_ptr<SoraDbgPlot::Task::Runnable> ContinueWith(std::shared_ptr<SoraDbgPlot::Task::Runnable> t)
{
if (_runnableContinue)
return _runnableContinue->ContinueWith(t);
else
{
_runnableContinue = t;
return t;
}
}
void Run()
{
auto func = _func;
auto dtor = _dtor;
auto runnableContinue = _runnableContinue;
_taskQueue->QueueTask([func, runnableContinue](){
func();
if (runnableContinue)
runnableContinue->Run();
}, [dtor, runnableContinue](){
dtor();
if (runnableContinue)
runnableContinue->Run();
});
}
private:
TaskSimple(const TaskSimple & other) {}
TaskSimple(TaskSimple && other) {}
private:
TaskQueue::TaskFunc _func;
TaskQueue::TaskFunc _dtor;
std::shared_ptr<TaskQueue> _taskQueue;
std::shared_ptr<Runnable> _runnableContinue;
};
}}

Просмотреть файл

@ -0,0 +1,52 @@
#include "TempBuffer.h"
using namespace SoraDbgPlot::Buffer;
static const int DEFAULT_KEPT_SIZE = 4*1024;
TempBuffer::TempBuffer()
{
_buf = 0;
_size = 0;
_sizeKept = DEFAULT_KEPT_SIZE;
}
TempBuffer::~TempBuffer()
{
if (_buf)
delete [] _buf;
}
void TempBuffer::ConfigKeptSize(int sizeKept)
{
_sizeKept = sizeKept;
}
char * TempBuffer::UseBuf(int size)
{
if (size <= _size)
{
return _buf;
}
else
{
if (_size > 0)
{
delete [] _buf;
_size = 0;
}
_buf = new char[size];
_size = size;
}
return _buf;
}
void TempBuffer::ReturnBuf()
{
if (_size > _sizeKept)
{
delete [] _buf;
_size = 0;
}
}

Просмотреть файл

@ -0,0 +1,19 @@
#pragma once
namespace SoraDbgPlot { namespace Buffer {
class TempBuffer
{
public:
TempBuffer();
~TempBuffer();
void ConfigKeptSize(int sizeKept);
char * UseBuf(int size);
void ReturnBuf();
private:
char * _buf;
int _size;
int _sizeKept;
};
}}

Просмотреть файл

@ -0,0 +1,165 @@
#include "TimeStampQueue.h"
TimeStampQueue::TimeStampQueue(size_t boundaryValue) {
_recordBoundary = boundaryValue;
}
bool TimeStampQueue::Search(size_t index, unsigned long long & timestamp)
{
size_t resIndex;
bool found = Search(index, resIndex);
if (found)
{
timestamp = _records[resIndex]._timestamp;
return true;
}
return false;
}
bool TimeStampQueue::SearchNearestTimeStamp(unsigned long long in, unsigned long long & out, size_t & outIdx)
{
if (_records.size() == 0)
return false;
DataRecord baseRecord = _records[0];
// binary search
size_t begin = 0;
size_t end = _records.size();
size_t middle;
while(end - begin > 1)
{
middle = (end + begin) / 2;
DataRecord record = _records[middle];
if (record._timestamp == in)
{
out = in;
outIdx = _records.size() - 1 - middle;
return true;
}
else if (record._timestamp < in)
{
begin = middle;
}
else
{
end = middle;
}
}
middle = begin;
DataRecord record = _records[middle];
out = in;
outIdx = _records.size() - 1 - middle;
if (record._timestamp < in)
{
return true;
}
else
{
return false;
}
}
void TimeStampQueue::AddRecord(const DataRecord & record)
{
size_t resIndex;
bool found = Search( record._start + record._size - 1, resIndex);
if (found)
{
size_t newStart = record._start + record._size;
auto iter = _records.begin() + resIndex;
size_t dist = newStart - iter->_start;
if (dist < 0)
dist += _recordBoundary;
else if (dist > _recordBoundary)
dist -= _recordBoundary;
if (dist < iter->_size) // modify the record
{
iter->_start = newStart % _recordBoundary;
iter->_size -= dist;
_records.erase(_records.begin(), _records.begin() + resIndex);
}
else // discard the record
{
_records.erase(_records.begin(), _records.begin() + resIndex + 1);
}
}
_records.push_back(record);
}
void TimeStampQueue::Reset()
{
_records.clear();
}
bool TimeStampQueue::GetDataRecord(size_t idx, DataRecord & record)
{
size_t size = Size();
if (idx >= size)
return false;
record = _records[size - idx - 1];
return true;
}
size_t TimeStampQueue::Size()
{
return _records.size();
}
bool TimeStampQueue::Search(size_t index, size_t & outIndex)
{
if (_records.size() == 0)
return false;
DataRecord baseRecord = _records[0];
// binary search
size_t begin = 0;
size_t end = _records.size();
if (index < baseRecord._start)
index += _recordBoundary;
if (index > baseRecord._start + _recordBoundary)
index -= _recordBoundary;
while(end - begin > 1)
{
size_t middle = (begin + end) / 2;
DataRecord record = _records[middle];
if (record._start < baseRecord._start)
record._start += _recordBoundary;
if (index < record._start)
{
end = middle;
}
else if (index >= record._start + record._size)
{
begin = middle;
}
else // find it
{
outIndex = middle;
return true;
}
}
DataRecord beginRecord = _records[begin];
if (beginRecord._start <= index &&
beginRecord._start + beginRecord._size > index)
{
outIndex = begin;
return true;
}
return false;
}

Просмотреть файл

@ -0,0 +1,36 @@
#pragma once
#include <deque>
#include <algorithm>
struct DataRecord
{
size_t _start;
size_t _size;
unsigned long long _timestamp;
};
class TimeStampQueue
{
public:
TimeStampQueue(size_t boundaryValue);
bool Search(size_t index, unsigned long long & timestamp);
bool SearchNearestTimeStamp(unsigned long long in, unsigned long long & out, size_t & outIdx);
void AddRecord(const DataRecord & record);
void Reset();
size_t Size();
bool GetDataRecord(size_t idx, DataRecord & record);
private:
std::deque<DataRecord> _records;
size_t _recordBoundary;
bool Search(size_t index, size_t & outIndex);
};

Просмотреть файл

@ -0,0 +1,108 @@
#pragma once
#include <functional>
#include <Windows.h>
namespace SoraDbgPlot { namespace Task {
class WaitableLatestTaskQueue
{
typedef std::function<void(void)> TaskType;
public:
WaitableLatestTaskQueue() {
::InitializeCriticalSection(&_cs);
_eventTaskComplete = ::CreateEvent(NULL, FALSE, TRUE, NULL);
_bTaskRunning = false;
_bTaskInQueue = false;
}
~WaitableLatestTaskQueue()
{
while(1)
{
bool bBreak = false;
::WaitForSingleObject(_eventTaskComplete, INFINITE);
::EnterCriticalSection(&_cs);
if (_bTaskRunning == false && _bTaskInQueue == false)
{
bBreak = true;
}
::LeaveCriticalSection(&_cs);
if (bBreak) break;
}
::CloseHandle(_eventTaskComplete);
::DeleteCriticalSection(&_cs);
}
void QueueTask(const TaskType & task)
{
bool bExecute = false;
::EnterCriticalSection(&_cs);
if (!_bTaskRunning)
{
_bTaskRunning = true;
_taskRunning = task;
bExecute = true;
}
else
{
_bTaskInQueue = true;
_taskInQueue = task;
}
::LeaveCriticalSection(&_cs);
if (bExecute)
ExecuteTask();
}
private:
void ExecuteTask()
{
QueueUserWorkItem(ThreadExecuteTask, this, WT_EXECUTEDEFAULT);
}
static DWORD WINAPI ThreadExecuteTask(__in LPVOID lpParameter)
{
auto queue = (WaitableLatestTaskQueue *)lpParameter;
queue->_taskRunning();
bool bExecute = false;
::EnterCriticalSection(&queue->_cs);
if (queue->_bTaskInQueue)
{
bExecute = true;
queue->_taskRunning = queue->_taskInQueue;
queue->_bTaskInQueue = false;
}
else
{
queue->_bTaskRunning = false;
}
::LeaveCriticalSection(&queue->_cs);
if (bExecute)
queue->ExecuteTask();
::SetEvent(queue->_eventTaskComplete);
return 0;
}
private:
volatile bool _bTaskInQueue;
volatile bool _bTaskRunning;
TaskType _taskInQueue;
TaskType _taskRunning;
CRITICAL_SECTION _cs;
HANDLE _eventTaskComplete;
};
}}

Просмотреть файл

@ -0,0 +1,10 @@
#pragma once
namespace SoraDbgPlot
{
class Writable
{
public:
virtual void Write(const void * ptr, size_t size, size_t & sizeWritten) = 0;
};
}

Просмотреть файл

@ -0,0 +1,6 @@
#pragma once
#include <memory>
#define SP(a) std::shared_ptr<a>
#define MSP(a) std::make_shared<a>

Просмотреть файл

Просмотреть файл

@ -0,0 +1,42 @@
#include "stdafx.h"
#include "AsyncObject.h"
using namespace std;
AsyncObject::AsyncObject()
{
_taskQueue = make_shared<SoraDbgPlot::Task::TaskQueue>();
}
AsyncObject::~AsyncObject()
{
}
void AsyncObject::DoLater(const std::function<void(void)> & f)
{
_taskQueue->QueueTask([f](){
f();
});
}
void AsyncObject::DoLater(const std::function<void(void)> & f, const std::function<void(void)> & dtor)
{
_taskQueue->QueueTask([f](){
f();
}, [dtor](){
dtor();
});
}
void AsyncObject::DoNow(const std::function<void(void)> & f)
{
_taskQueue->DoTask([f](){
f();
});
}
std::shared_ptr<SoraDbgPlot::Task::TaskQueue> AsyncObject::TaskQueue()
{
return _taskQueue;
}

Просмотреть файл

@ -0,0 +1,19 @@
#pragma once
#include <memory>
#include <functional>
#include "TaskQueue.h"
class AsyncObject : public std::enable_shared_from_this<AsyncObject>
{
public:
AsyncObject();
virtual ~AsyncObject();
void DoLater(const std::function<void(void)> & f);
void DoLater(const std::function<void(void)> & f, const std::function<void(void)> & dtor);
void DoNow(const std::function<void(void)> & f);
std::shared_ptr<SoraDbgPlot::Task::TaskQueue> TaskQueue();
private:
std::shared_ptr<SoraDbgPlot::Task::TaskQueue> _taskQueue;
};

Просмотреть файл

@ -0,0 +1,93 @@
// AutoLayoutSlider.cpp : implementation file
//
#include "stdafx.h"
#include "DbgPlotViewer.h"
#include "AutoLayoutSlider.h"
// AutoLayoutSlider
IMPLEMENT_DYNAMIC(AutoLayoutSlider, CWnd)
AutoLayoutSlider::AutoLayoutSlider()
{
}
AutoLayoutSlider::~AutoLayoutSlider()
{
}
BEGIN_MESSAGE_MAP(AutoLayoutSlider, CWnd)
ON_WM_CREATE()
ON_WM_SIZE()
ON_WM_HSCROLL()
END_MESSAGE_MAP()
// AutoLayoutSlider message handlers
int AutoLayoutSlider::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
CRect rectDummy;
rectDummy.SetRectEmpty();
this->_sliderCtrl.Create(WS_CHILD | WS_VISIBLE, rectDummy, this, 1);
this->_sliderCtrl.SetRange(0, 80, 1); // hard code!!!
return 0;
}
void AutoLayoutSlider::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy);
// TODO: Add your message handler code here
_sliderCtrl.MoveWindow(0, 0, cx, cy, 1);
}
void AutoLayoutSlider::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// TODO: Add your message handler code here and/or call default
switch (nSBCode)
{
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
{
int pos = nPos*5 + 100; // hard code!!!
EventAutoScale.Raise(this, pos);
}
break;
case SB_ENDSCROLL:
{
int pos = this->_sliderCtrl.GetPos()*5 + 100; // hard code!!!
EventAutoScale.Raise(this, pos);
}
break;
}
CWnd::OnHScroll(nSBCode, nPos, pScrollBar);
}
void AutoLayoutSlider::PostNcDestroy()
{
// TODO: Add your specialized code here and/or call the base class
EventAutoScale.Reset();
CWnd::PostNcDestroy();
}

Просмотреть файл

@ -0,0 +1,28 @@
#pragma once
// AutoLayoutSlider
class AutoLayoutSlider : public CWnd
{
DECLARE_DYNAMIC(AutoLayoutSlider)
public:
AutoLayoutSlider();
virtual ~AutoLayoutSlider();
SoraDbgPlot::Event::Event<int> EventAutoScale;
private:
CSliderCtrl _sliderCtrl;
protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
virtual void PostNcDestroy();
};

Просмотреть файл

@ -0,0 +1,91 @@
// BaseProperty.cpp : implementation file
//
#include "stdafx.h"
#include "BaseProperty.h"
// BaseProperty
IMPLEMENT_DYNAMIC(BaseProperty, CMFCPropertyGridCtrl)
BaseProperty::BaseProperty()
{
}
BaseProperty::~BaseProperty()
{
_pvTaskQueue.Execute(true);
}
void BaseProperty::CloseProperty()
{
this->OnCloseProperty();
}
BEGIN_MESSAGE_MAP(BaseProperty, CMFCPropertyGridCtrl)
ON_WM_CREATE()
ON_MESSAGE(WMME_EXE_TASKQUEUE, OnExeTaskQueue)
END_MESSAGE_MAP()
// BaseProperty message handlers
int BaseProperty::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CMFCPropertyGridCtrl::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
this->EnableHeaderCtrl(FALSE);
this->EnableDescriptionArea();
this->SetVSDotNetLook();
this->MarkModifiedProperties();
return 0;
}
CMFCPropertyGridProperty * BaseProperty::FindProperty(const wchar_t * name) const
{
CMFCPropertyGridProperty * property = NULL;
for (int i = 0; i < this->GetPropertyCount(); i++)
{
CMFCPropertyGridProperty * aProperty = this->GetProperty(i);
if (wcscmp(aProperty->GetName(), name) == 0)
{
property = aProperty;
break;
}
}
return property;
}
void BaseProperty::PostNcDestroy()
{
// TODO: Add your specialized code here and/or call the base class
this->OnCloseProperty();
EventClosed.Raise(this, true);
CMFCPropertyGridCtrl::PostNcDestroy();
}
LRESULT BaseProperty::OnExeTaskQueue(WPARAM wParam, LPARAM lParam)
{
_pvTaskQueue.Execute(false);
return 0;
}
void BaseProperty::DoLater(std::function<void(bool)> f)
{
_pvTaskQueue.Queue(f);
HWND hWnd = m_hWnd;
if (hWnd)
::PostMessage(hWnd, WMME_EXE_TASKQUEUE, 0, 0);
}

Просмотреть файл

@ -0,0 +1,38 @@
#pragma once
#include <memory>
#include <string>
#include "Event.h"
#include "CSRecursiveLock.h"
#include "PassiveTaskQueue.h"
// BaseProperty
#define WMME_EXE_TASKQUEUE (WM_APP+1)
class BaseProperty : public CMFCPropertyGridCtrl
{
DECLARE_DYNAMIC(BaseProperty)
public:
BaseProperty();
virtual ~BaseProperty();
void CloseProperty();
SoraDbgPlot::Event::Event<bool> EventClosed;
void DoLater(std::function<void(bool)>);
protected:
virtual void OnCloseProperty() = 0;
private:
PassiveTaskQueue _pvTaskQueue;
protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg LRESULT OnExeTaskQueue(WPARAM, LPARAM);
protected:
CMFCPropertyGridProperty * FindProperty(const wchar_t * name) const;
virtual void PostNcDestroy();
};

Просмотреть файл

@ -0,0 +1,219 @@
#include "stdafx.h"
#include "BitmapPlotWnd.h"
BEGIN_MESSAGE_MAP(BitmapPlotWnd, CPlotWnd)
ON_WM_CREATE()
ON_WM_SIZE()
END_MESSAGE_MAP()
BitmapPlotWnd::BitmapPlotWnd(void * userData) :
CPlotWnd(userData)
{
_userData = userData;
}
int BitmapPlotWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if ( CPlotWnd::OnCreate(lpCreateStruct) == -1 )
return -1;
CRect rectDummy;
rectDummy.SetRectEmpty();
_canvasWnd = new CWnd();
_canvasWnd->Create(NULL, L"control", WS_CHILD | WS_VISIBLE, rectDummy, this, 0);
_controlWnd = new PlayControlWnd;
_controlWnd->EventPlayClicked.Subscribe([this](const void * sender, const PlayControlWnd::PlayPauseEvent e){
PlayPauseEvent ee;
ee.IsPlay = e.IsPlay;
this->EventPlayClicked.Raise(this, ee);
});
_controlWnd->EventSpeedClicked.Subscribe([this](const void * sender, const PlayControlWnd::SpeedChangeEvent e){
SpeedChangeEvent ee;
ee.IsUp = e.IsUp;
this->EventSpeedClicked.Raise(this, ee);
});
_controlWnd->EventTrackBarSeeked.Subscribe([this](const void * sender, const PlayControlWnd::TrackBarSeekEvent & e) {
SeekEvent ee;
ee.Pos = e.Pos;
this->EventSeek.Raise(this, ee);
});
_controlWnd->Create(NULL, L"control", WS_CHILD | WS_VISIBLE, rectDummy, _canvasWnd, 0);
_subBitmapWnd = new SubBitmapPlotWnd(_userData);
_subBitmapWnd->EventWheel.Subscribe([this](const void * sender, const SubBitmapPlotWnd::WheelEvent & e) {
WheelEvent ee;
ee.IsUp = e.IsUp;
this->EventWheel.Raise(this, ee);
});
_subBitmapWnd->EventClicked.Subscribe([this](const void * sender, const SubBitmapPlotWnd::ClickEvent & e) {
this->BringWindowToTop();
CPlotWnd::BringToFrontEvent ee;
this->EventBringToFront.Raise(this, ee);
});
_subBitmapWnd->Create(NULL, L"bitmap", WS_CHILD | WS_VISIBLE, rectDummy, _canvasWnd, 0);
return 0;
}
void BitmapPlotWnd::OnSize(UINT nType, int cx, int cy)
{
const int CTRL_WND_HEIGHT = 17;
CRect clientRect;
this->CalcClientRect(&clientRect);
CRect canvasRect = clientRect;
_canvasWnd->MoveWindow(&canvasRect);
CRect controlRect;
controlRect.SetRectEmpty();
controlRect.right += clientRect.Width();
controlRect.bottom += clientRect.Height();
controlRect.top = controlRect.bottom - CTRL_WND_HEIGHT;
_controlWnd->MoveWindow(&controlRect, 1);
if (true)
{
CRect graphRect;
graphRect.SetRectEmpty();
graphRect.right += clientRect.Width();
graphRect.bottom = controlRect.top;
_subBitmapWnd->MoveWindow(&graphRect, 1);
ResizeEvent e;
e.cx = graphRect.Width();
e.cy = graphRect.Height();
this->EventBitmapResize.Raise(this, e);
}
CPlotWnd::OnSize(nType, cx, cy);
}
void BitmapPlotWnd::SetButtonStatePlay()
{
this->Invoke([this](bool close){
if (close)
return;
if (_controlWnd->m_hWnd)
_controlWnd->SetButtonStatePlay();
});
}
void BitmapPlotWnd::SetButtonStatePause()
{
this->Invoke([this](bool close){
if (close)
return;
if (_controlWnd->m_hWnd)
_controlWnd->SetButtonStatePause();
});
}
void BitmapPlotWnd::SetTrackBarViewWndRange(double right, double range)
{
this->Invoke([this, right, range](bool close){
if (close)
return;
if (_controlWnd->m_hWnd)
_controlWnd->SetTrackBarWndPos(right, range);
});
}
void BitmapPlotWnd::SetBitmap(Bitmap * bitmap)
{
this->Invoke([this, bitmap](bool close){
if (close)
{
delete bitmap;
return;
}
if (_subBitmapWnd->m_hWnd)
this->_subBitmapWnd->SetBitmap(bitmap);
else
delete bitmap;
});
}
BitmapPlotWnd::~BitmapPlotWnd()
{
if (_controlWnd)
{
delete _controlWnd;
_controlWnd = 0;
}
if (_subBitmapWnd)
{
delete _subBitmapWnd;
_subBitmapWnd = 0;
}
if (_canvasWnd)
{
delete _canvasWnd;
_canvasWnd = 0;
}
}
void BitmapPlotWnd::AddSubPlotWnd(SubPlotWnd * subWnd, const CRect & rect)
{
this->Invoke([this, subWnd, rect](bool close){
if (close)
return;
if (m_hWnd == 0 || _subBitmapWnd->m_hWnd == 0)
return;
CRect rect2 = rect;
this->_subBitmapWnd->ScreenToClient(rect2);
subWnd->CreateEx(0, NULL, L"", WS_CHILD | WS_VISIBLE, rect2, this->_subBitmapWnd, 0, 0);
});
}
void BitmapPlotWnd::AddSubPlotWndRelative(SubPlotWnd * subWnd, const CRect & rect)
{
this->Invoke([this, subWnd, rect](bool close){
if (close)
return;
if (m_hWnd == 0 || _subBitmapWnd->m_hWnd == 0)
return;
CRect rect2 = rect;
subWnd->CreateEx(0, NULL, L"", WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS, rect2, this->_subBitmapWnd, 0, 0);
});
}
void * BitmapPlotWnd::UserData()
{
return _userData;
}
void BitmapPlotWnd::MyScreenToClient(CRect & rect)
{
this->_subBitmapWnd->ScreenToClient(&rect);
}
void BitmapPlotWnd::MyScreenToClient(CPoint & point)
{
this->_subBitmapWnd->ScreenToClient(&point);
}
void BitmapPlotWnd::EnableSpeedButtons(bool bEnable)
{
this->Invoke([this, bEnable](bool close){
if (close) return;
this->_controlWnd->EnableSpeedButtons(bEnable);
});
}

Просмотреть файл

@ -0,0 +1,52 @@
#pragma once
#include "PlotWnd.h"
#include "PlayControlWnd.h"
#include "SubBitmapPlotWnd.h"
#include "Targetable.h"
class BitmapPlotWnd : public CPlotWnd
{
public:
BitmapPlotWnd(void * userData);
~BitmapPlotWnd();
public:
PlayControlWnd * _controlWnd;
SubBitmapPlotWnd * _subBitmapWnd;
CWnd * _canvasWnd;
struct PlayPauseEvent { bool IsPlay; };
struct SpeedChangeEvent { bool IsUp; };
struct SeekEvent { double Pos; };
struct WheelEvent { bool IsUp; };
struct ResizeEvent { int x; int y; int cx; int cy; };
SoraDbgPlot::Event::Event<PlayPauseEvent> EventPlayClicked;
SoraDbgPlot::Event::Event<SpeedChangeEvent> EventSpeedClicked;
SoraDbgPlot::Event::Event<SeekEvent> EventSeek;
SoraDbgPlot::Event::Event<WheelEvent> EventWheel;
SoraDbgPlot::Event::Event<ResizeEvent> EventBitmapResize;
void SetBitmap(Bitmap * bitmap);
void SetButtonStatePlay();
void SetButtonStatePause();
void SetTrackBarViewWndRange(double right, double range);
void MyScreenToClient(CRect &);
void MyScreenToClient(CPoint &);
void EnableSpeedButtons(bool bEnable);
protected:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnSize(UINT nType, int cx, int cy);
DECLARE_MESSAGE_MAP()
public:
void AddSubPlotWnd(SubPlotWnd * subWnd, const CRect & rect);
void AddSubPlotWndRelative(SubPlotWnd * subWnd, const CRect & rect);
public:
void * UserData();
private:
void * _userData;
};

Просмотреть файл

@ -0,0 +1,24 @@
#include "stdafx.h"
#include <math.h>
#include "BitmapTypeSettings.h"
double SettingGetBitmapRangeMax(bool isLog)
{
double maxNormal = (double)INT_MAX * 10.0;
return isLog ? log10(maxNormal) : maxNormal;
}
double SettingGetBitmapRangeMin(bool isLog)
{
double maxNormal = (double)INT_MAX * 10.0;
double minNormal = (double)INT_MIN * 10.0;
return isLog ? -log10(maxNormal) : minNormal;
}
double SettingGetBitmapRangeHalfDelta(bool isLog)
{
if (isLog)
return 0.001;
else
return 1.0;
}

Просмотреть файл

@ -0,0 +1,5 @@
#pragma once
double SettingGetBitmapRangeMax(bool isLog);
double SettingGetBitmapRangeMin(bool isLog);
double SettingGetBitmapRangeHalfDelta(bool isLog);

Просмотреть файл

@ -0,0 +1,7 @@
#include "stdafx.h"
#include "ChannelAddable.h"
void ChannelAddable::Clear()
{
PropObject::Clear();
}

Просмотреть файл

@ -0,0 +1,14 @@
#pragma once
#include <memory>
#include "ProcessOpened.h"
#include "ChannelOpened.h"
class ChannelAddable : public PropObject
{
public:
virtual void Highlight(bool bHighlight) = 0;
virtual bool Accept(std::shared_ptr<ChannelOpened>, CPoint pointIn, CPoint & pointOut) = 0;
virtual void RequestAddChannel(std::shared_ptr<ProcessOpened>, std::shared_ptr<ChannelOpened>, CPoint pointIn) = 0;
void Clear();
};

Просмотреть файл

@ -0,0 +1,297 @@
#include "stdafx.h"
#include <memory>
#include "ChannelOpened.h"
#include "SharedChannel.h"
#include "ChannelProperty.h"
#include "HelperFunc.h"
using namespace std;
using namespace SoraDbgPlot::Task;
using namespace SoraDbgPlot::SharedObj;
ChannelOpened::ChannelOpened() :
_color(RGB(200, 200, 200))
{
_spectrumSize = 1;
_openCount = 0;
_bAttatched = false;
}
ChannelOpened::~ChannelOpened()
{
_sharedChannel.reset();
}
void ChannelOpened::AttatchSharedChannelSync(shared_ptr<SoraDbgPlot::SharedObj::SharedChannel> sch)
{
auto shared_me = dynamic_pointer_cast<ChannelOpened, AsyncObject>(shared_from_this());
TaskQueue()->DoTask([shared_me, sch](){
if (sch)
{
if (shared_me->_sharedChannel)
{
shared_me->_sharedChannel->StrategyNewData.UnSet();
shared_me->_sharedChannel.reset();
}
shared_me->_sharedChannel = sch;
shared_me->_id = sch->Id();
shared_me->_pid = sch->Pid();
shared_me->_spectrumSize = sch->SpectrumDataSize();
shared_me->_type = sch->Type();
shared_me->_name = sch->Name();
shared_me->_bAttatched = true;
shared_me->ClearData();
}
});
}
void ChannelOpened::DeattatchSharedChannelSync()
{
auto SThis = dynamic_pointer_cast<ChannelOpened, AsyncObject>(shared_from_this());
TaskQueue()->DoTask([SThis](){
SThis->_sharedChannel.reset();
SThis->_pid = -1;
SThis->_bAttatched = false;
});
}
bool ChannelOpened::IsAttatched()
{
return _bAttatched;
}
int ChannelOpened::Id()
{
int ret;
auto shared_me = dynamic_pointer_cast<ChannelOpened, AsyncObject>(shared_from_this());
TaskQueue()->DoTask([this, &ret](){
ret = _id;
});
return ret;
}
int ChannelOpened::Pid()
{
int ret;
TaskQueue()->DoTask([this, &ret](){
ret = _pid;
});
return ret;
}
int ChannelOpened::SpectrumDataSize()
{
int ret;
TaskQueue()->DoTask([this, &ret](){
ret = _spectrumSize;
});
return ret;
}
wstring ChannelOpened::Name()
{
wstring ret;
TaskQueue()->DoTask([this, &ret](){
ret = _name;
});
return std::move(ret);
}
ChannelType ChannelOpened::Type()
{
ChannelType ret;
TaskQueue()->DoTask([this, &ret](){
ret = _type;
});
return ret;
}
void ChannelOpened::SetColor(COLORREF color)
{
auto shared_me = dynamic_pointer_cast<ChannelOpened, AsyncObject>(shared_from_this());
TaskQueue()->QueueTask([shared_me, color](){
shared_me->_color = color;
});
}
COLORREF ChannelOpened::Color()
{
COLORREF color;
auto shared_me = dynamic_pointer_cast<ChannelOpened, AsyncObject>(shared_from_this());
TaskQueue()->DoTask([shared_me, &color](){
color = shared_me->_color;
});
return color;
}
void ChannelOpened::Release()
{
auto SThis = dynamic_pointer_cast<ChannelOpened, AsyncObject>(shared_from_this());
TaskQueue()->DoTask([SThis](){
SThis->TaskFunc_Release();
});
}
void ChannelOpened::TaskFunc_Release()
{
if (_sharedChannel)
{
_sharedChannel.reset();
_pid = -1;
}
}
std::shared_ptr<TaskSimple> ChannelOpened::TaskUpdateData(std::shared_ptr<bool> updated)
{
auto SThis = dynamic_pointer_cast<ChannelOpened, AsyncObject>(shared_from_this());
shared_ptr<TaskSimple> task;
task = make_shared<TaskSimple>(TaskQueue(), [SThis, updated](){
if (updated.get())
*updated = false;
if (SThis->_sharedChannel)
{
auto dataList = SThis->_sharedChannel->CheckOut();
while(dataList->size() > 0)
{
if (updated.get())
*updated = true;
auto iter = dataList->front();
SThis->WriteData(iter.ptr, iter.length);
dataList->pop_front();
}
}
//TRACE1("ChannelOpened::TaskUpdateData [%d]\n", SThis->Id());
});
return task;
}
void ChannelOpened::WriteData(const char * data, size_t length)
{
// do nothint
}
std::shared_ptr<BaseProperty> ChannelOpened::CreatePropertyPage()
{
shared_ptr<ChannelProperty> propertyPage;
auto SThis = dynamic_pointer_cast<ChannelOpened, AsyncObject>(shared_from_this());
TaskQueue()->DoTask([SThis, &propertyPage](){
wstring typeName = SThis->GetTypeName();
propertyPage = make_shared<ChannelProperty>(typeName, SThis->_name, SThis->_color);
auto SThis2 = SThis;
propertyPage->EventColor.Subscribe([SThis2](const void * sender, const COLORREF & color){
auto SThis3 = SThis2;
auto color2 = color;
SThis3->DoLater([SThis3, color2](){
SThis3->_color = color2;
SThis3->OnColorUpdated();
});
});
});
return propertyPage;
}
void ChannelOpened::OnColorUpdated()
{
// do nothing
}
void ChannelOpened::GetRect(CRect & rect)
{
rect.SetRectEmpty();
}
HRESULT ChannelOpened::CreateXmlElement(IXMLDOMDocument *pDom, IXMLDOMElement *pParent)
{
IXMLDOMElement *pElement=NULL;
CreateAndAddElementNode(pDom, L"Channel", L"\n\t\t", pParent, &pElement);
this->AppendXmlProperty(pDom, pElement);
CreateAndAddTextNode(pDom, L"\n\t\t", pElement);
return S_OK;
}
HRESULT ChannelOpened::AppendXmlProperty(IXMLDOMDocument *pDom, IXMLDOMElement *pParent)
{
auto SThis = dynamic_pointer_cast<ChannelOpened, AsyncObject>(shared_from_this());
this->DoNow([SThis, pDom, pParent](){
IXMLDOMElement *pElement = NULL;
CreateAndAddElementNode(pDom, L"SName", L"\n\t\t\t", pParent, &pElement);
pElement->put_text((_bstr_t)SThis->_name.c_str());
CreateAndAddElementNode(pDom, L"SType", L"\n\t\t\t", pParent, &pElement);
pElement->put_text(_bstr_t(typeid(*SThis).name()));
CreateAndAddElementNode(pDom, L"color", L"\n\t\t\t", pParent, &pElement);
pElement->put_text((_bstr_t)SThis->_color);
});
return S_OK;
}
HRESULT ChannelOpened::LoadXmlElement(MSXML2::IXMLDOMNodePtr pElement)
{
CString cs;
MSXML2::IXMLDOMNodePtr pNode;
pNode = pElement->selectSingleNode(L"SName");
if (pNode == 0)
{
this->_name = L"invalid name";
}
else
{
cs.Format(_T("%S"),(LPCSTR)pNode->text);
this->_name = cs;
}
pNode = pElement->selectSingleNode(L"color");
if (pNode != 0)
{
this->_color = (atol)((LPCSTR)pNode->text);
}
return S_OK;
}
bool ChannelOpened::Export(const CString &, bool bAll)
{
//::AfxMessageBox(L"not implemented");
return false;
}
void ChannelOpened::Clear()
{
// do nothing
}
void ChannelOpened::SetOpenState(bool bOpened)
{
if (bOpened)
::InterlockedIncrement(&_openCount);
else
::InterlockedDecrement(&_openCount);
}
bool ChannelOpened::GetOpenState()
{
return _openCount > 0;
}

Просмотреть файл

@ -0,0 +1,63 @@
#pragma once
#include <memory>
#include "SharedChannel.h"
#include "TaskSimple.h"
#include "PropObject.h"
#include "BaseProperty.h"
class ChannelOpened : public PropObject
{
public:
ChannelOpened();
~ChannelOpened();
void AttatchSharedChannelSync(std::shared_ptr<SoraDbgPlot::SharedObj::SharedChannel>);
void DeattatchSharedChannelSync();
int Id();
int Pid();
int SpectrumDataSize();
std::wstring Name();
ChannelType Type();
COLORREF Color();
void Release();
bool IsAttatched();
virtual void Clear();
virtual bool Export(const CString &, bool bAll);
virtual std::shared_ptr<SoraDbgPlot::Task::TaskSimple> TaskUpdateData(std::shared_ptr<bool>);
virtual void WriteData(const char * data, size_t length);
virtual void GetRect(CRect & rect);
void SetColor(COLORREF color);
void TaskFunc_Release();
virtual HRESULT CreateXmlElement(IXMLDOMDocument *pDom, IXMLDOMElement *pe);
virtual HRESULT AppendXmlProperty(IXMLDOMDocument *pDom, IXMLDOMElement *pParent);
virtual HRESULT LoadXmlElement(MSXML2::IXMLDOMNodePtr pElement);
void SetOpenState(bool bOpened);
bool GetOpenState();
private:
std::shared_ptr<SoraDbgPlot::SharedObj::SharedChannel> _sharedChannel;
volatile long _openCount;
bool _bAttatched;
protected:
int _id;
int _pid;
ChannelType _type;
std::wstring _name;
protected:
COLORREF _color;
int _spectrumSize;
protected:
std::shared_ptr<BaseProperty> CreatePropertyPage();
virtual void OnColorUpdated();
virtual void ClearData() = 0;
};

Просмотреть файл

@ -0,0 +1,170 @@
#include "stdafx.h"
#include <memory>
#include "TaskQueue.h"
#include "ChannelOpenedDots.h"
using namespace std;
using namespace SoraDbgPlot::Task;
shared_ptr<BaseProperty> ChannelOpenedDots::CreatePropertyPage()
{
return ChannelOpened::CreatePropertyPage();
}
void ChannelOpenedDots::Task_ProcessDrawDotsParam(std::shared_ptr<DrawDotsParam> param, bool bDrawOrGet)
{
if ( (bDrawOrGet == true) && (param->_bMaxInitialized == false) )
return;
if (bDrawOrGet)
{
this->_latestIndex = param->_index;
this->_range = param->_range;
}
if (bDrawOrGet == false)
{
unsigned long long timestamp;
bool succ = this->IndexToTimestamp(param->_index, timestamp);
if (succ)
{
if (!param->_bTimeStampTaken)
{
param->_timeStamp = timestamp;
param->_bTimeStampTaken = true;
}
else
{
param->_timeStamp = max(param->_timeStamp, timestamp);
}
}
}
Graphics * g = param->_g;
CRect rect = param->_rect;
size_t start = param->_index;
size_t size = param->_range;
bool luminescence = param->_luminescence;
double dispMax = param->_dispMaxValue;
CRect rectClient = rect;
double oldRange = dispMax * 2;
int newRangeX = rectClient.Width();
int newRangeY = rectClient.Height();
Gdiplus::Color color;
color.SetFromCOLORREF(this->_color);
int redColor = color.GetRed();
int greenColor = color.GetGreen();
int blueColor = color.GetBlue();
for (size_t i = 0; i < size; i++)
{
size_t mappedIdx = start + i;
if (mappedIdx >= _ringBuffer->Size() || mappedIdx < 0)
continue;
COMPLEX16 y = (*_ringBuffer)[mappedIdx];
if (bDrawOrGet)
{
Gdiplus::REAL re = float((y.re - (-dispMax)) * newRangeX / oldRange + rectClient.left);
Gdiplus::REAL im = float((rectClient.bottom - (y.im - (-dispMax)) * newRangeY / oldRange));
int alphaDot;
if (luminescence)
alphaDot = 255 * (size - i) / size;
else
alphaDot = 255;
Gdiplus::Color colorFrame(alphaDot, redColor, greenColor, blueColor);
Pen pen(colorFrame);
g->DrawLine(&pen, re-1.0f, im, re+1.0f, im);
g->DrawLine(&pen, re, im-1.0f, re, im+1.0f);
}
else
{
if (!param->_bMaxInitialized)
{
param->_dispMaxValue = y.re * y.re + y.im * y.im;
param->_bMaxInitialized = true;
}
else
{
param->_dispMaxValue = max(param->_dispMaxValue, y.re * y.re + y.im * y.im);
}
}
}
if (bDrawOrGet == false)
if (param->_dispMaxValue > 0)
{
param->_dispMaxValue = sqrt(param->_dispMaxValue);
}
}
std::shared_ptr<SoraDbgPlot::Task::TaskSimple> ChannelOpenedDots::TaskProcessData(std::shared_ptr<DrawDotsParam> param, bool bDrawOrGet)
{
auto SThis = dynamic_pointer_cast<ChannelOpenedDots, AsyncObject>(shared_from_this());
return make_shared<TaskSimple>(TaskQueue(), [SThis, param, bDrawOrGet](){
SThis->Task_ProcessDrawDotsParam(param, bDrawOrGet);
});
}
const wchar_t * ChannelOpenedDots::GetTypeName()
{
return L"Dots Channel";
}
bool ChannelOpenedDots::Export(const CString & filename, bool bAll)
{
auto SThis = dynamic_pointer_cast<ChannelOpenedDots, AsyncObject>(shared_from_this());
this->DoLater([SThis, filename, bAll](){
FILE * fp;
errno_t ret = _wfopen_s(&fp, filename, L"wb");
if (ret == 0)
{
char * digitBuf = new char[128];
if (bAll)
{
SThis->_ringBuffer->Export([fp, digitBuf](const COMPLEX16 * ptr, size_t length){
while(length > 0)
{
fprintf(fp, "%d %d\r\n", (*ptr).re, (*ptr).im);
ptr++;
length --;
}
});
}
else
{
size_t start = SThis->_latestIndex;
size_t length = SThis->_range;
length = min(length, SThis->_ringBuffer->Size());
SThis->_ringBuffer->ExportRange(start, length, [fp, digitBuf](const COMPLEX16 * ptr, size_t length){
while(length > 0)
{
fprintf(fp, "%d %d\r\n", (*ptr).re, (*ptr).im);
ptr++;
length --;
}
});
}
delete [] digitBuf;
fclose(fp);
}
});
return true;
}

Просмотреть файл

@ -0,0 +1,46 @@
#pragma once
#include "ChannelOpenedFixedLengthType.h"
#include "Event.h"
#include "TaskQueue.h"
#include "TaskSimple.h"
#include "FrameWithSizeFilter.h"
#include "RingBufferWithTimeStamp.h"
#pragma once
#ifndef _SORA_
typedef struct tagComplex16
{
short re;
short im;
} COMPLEX16;
#endif
struct DrawDotsParam
{
Graphics * _g;
bool _bIsLog;
CRect _rect;
double _dispMaxValue;
size_t _index;
size_t _range;
bool _luminescence;
bool _bMaxInitialized;
bool _bTimeStampTaken;
unsigned long long _timeStamp;
};
class ChannelOpenedDots : public ChannelOpenedFixedLengthType<COMPLEX16>
{
public:
std::shared_ptr<SoraDbgPlot::Task::TaskSimple> TaskProcessData(std::shared_ptr<DrawDotsParam>, bool bDrawOrGet);
virtual std::shared_ptr<BaseProperty> CreatePropertyPage();
virtual const wchar_t * GetTypeName();
virtual bool Export(const CString &, bool bAll);
private:
void Task_ProcessDrawDotsParam(std::shared_ptr<DrawDotsParam> param, bool bDrawOrGet);
};

Просмотреть файл

@ -0,0 +1,2 @@
#include "stdafx.h"
#include "ChannelOpenedFixedLengthType.h"

Просмотреть файл

@ -0,0 +1,96 @@
#pragma once
#include <memory>
#include "ChannelOpened.h"
#include "RingBufferWithTimeStamp.h"
#include "FrameWithSizeFilter.h"
#include "TaskSimple.h"
#include "AppSettings.h"
template <typename T>
class ChannelOpenedFixedLengthType : public ChannelOpened
{
protected:
virtual void WriteData(const char * data, size_t length);
virtual void ClearData();
public:
ChannelOpenedFixedLengthType();
~ChannelOpenedFixedLengthType();
bool IndexToTimestamp(size_t index, unsigned long long & timestamp);
bool Data(size_t index, T & data);
size_t DataSize();
virtual std::shared_ptr<SoraDbgPlot::Task::TaskSimple> TaskUpdateDataSize(std::shared_ptr<size_t>);
protected:
SoraDbgPlot::FrameWithSizeInfoWriter<T> * _filter;
RingBufferWithTimeStamp<T> * _ringBuffer;
size_t _latestIndex;
size_t _range;
};
template <typename T>
void ChannelOpenedFixedLengthType<T>::WriteData(const char * data, size_t length)
{
auto SThis = std::dynamic_pointer_cast<ChannelOpenedFixedLengthType, AsyncObject>(shared_from_this());
TaskQueue()->QueueTask([SThis, data, length](){
size_t dummy;
SThis->_filter->Write(data, length, dummy);
delete [] data;
}, [data](){
delete [] data;
});
}
template <typename T>
ChannelOpenedFixedLengthType<T>::ChannelOpenedFixedLengthType()
{
_ringBuffer = new RingBufferWithTimeStamp<T>(::SettingGetReplayBufferSize() / sizeof(T));
_filter = new SoraDbgPlot::FrameWithSizeInfoWriter<T>(_ringBuffer);
_latestIndex = 0;
_range = 0;
}
template <typename T>
ChannelOpenedFixedLengthType<T>::~ChannelOpenedFixedLengthType()
{
delete _filter;
delete _ringBuffer;
}
template <typename T>
bool ChannelOpenedFixedLengthType<T>::Data(size_t index, T & data)
{
data = (*_ringBuffer)[index];
return true;
}
template <typename T>
size_t ChannelOpenedFixedLengthType<T>::DataSize()
{
return _ringBuffer->Size();
}
template <typename T>
bool ChannelOpenedFixedLengthType<T>::IndexToTimestamp(size_t index, unsigned long long & timestamp)
{
return _ringBuffer->GetTimeStampBySample(index, timestamp);
}
template <typename T>
std::shared_ptr<SoraDbgPlot::Task::TaskSimple> ChannelOpenedFixedLengthType<T>::TaskUpdateDataSize(std::shared_ptr<size_t> size)
{
auto SThis = std::dynamic_pointer_cast<ChannelOpenedFixedLengthType, AsyncObject>(shared_from_this());
return std::make_shared<SoraDbgPlot::Task::TaskSimple>(TaskQueue(), [SThis, size](){
size_t oldSize = *size;
size_t newSize = max(oldSize, SThis->_ringBuffer->Size());
*size = newSize;
});
}
template <typename T>
void ChannelOpenedFixedLengthType<T>::ClearData()
{
_ringBuffer->Reset();
}

Просмотреть файл

@ -0,0 +1,67 @@
#include "stdafx.h"
#include <assert.h>
#include <memory>
#include "ChannelOpenedLine.h"
#include "TaskQueue.h"
#include "ChannelProperty.h"
using namespace std;
using namespace SoraDbgPlot::Task;
shared_ptr<BaseProperty> ChannelOpenedLine::CreatePropertyPage()
{
return ChannelOpened::CreatePropertyPage();
}
const wchar_t * ChannelOpenedLine::GetTypeName()
{
return L"Line Channel";
}
bool ChannelOpenedLine::Export(const CString & filename, bool bAll)
{
auto SThis = dynamic_pointer_cast<ChannelOpenedLine, AsyncObject>(shared_from_this());
this->DoLater([SThis, filename, bAll](){
FILE * fp;
errno_t ret = _wfopen_s(&fp, filename, L"wb");
if (ret == 0)
{
char * digitBuf = new char[128];
if (bAll)
{
SThis->_ringBuffer->Export([fp, digitBuf](const int * ptr, size_t length){
while(length > 0)
{
fprintf(fp, "%d\r\n", *ptr);
ptr ++;
length --;
}
});
}
else
{
size_t start = SThis->_latestIndex;
size_t length = SThis->_range;
length = min(length, SThis->_ringBuffer->Size());
SThis->_ringBuffer->ExportRange(start, length, [fp, digitBuf](const int * ptr, size_t length){
while(length > 0)
{
fprintf(fp, "%d\r\n", *ptr);
ptr ++;
length --;
}
});
}
delete [] digitBuf;
fclose(fp);
}
});
return true;
}

Просмотреть файл

@ -0,0 +1,11 @@
#pragma once
#include "ChannelOpenedLineType.h"
#include "TaskQueue.h"
class ChannelOpenedLine : public ChannelOpenedLineType
{
public:
virtual std::shared_ptr<BaseProperty> CreatePropertyPage();
virtual const wchar_t * GetTypeName();
virtual bool Export(const CString &, bool bAll);
};

Просмотреть файл

@ -0,0 +1,396 @@
#include "stdafx.h"
#include <Windows.h>
#include "ChannelOpenedLineType.h"
#include "Event.h"
#include "TaskQueue.h"
#include "HelperFunc.h"
using namespace std;
using namespace SoraDbgPlot::Task;
ChannelOpenedLineType::ChannelOpenedLineType()
{
_drawUsingSample = true; // defaut using sample
}
shared_ptr<SoraDbgPlot::Task::TaskSimple> ChannelOpenedLineType::LineDataTask(std::shared_ptr<LineDataParam> param)
{
auto shared_me = dynamic_pointer_cast<ChannelOpenedLineType, AsyncObject>(shared_from_this());
return make_shared<TaskSimple>(TaskQueue(), [shared_me, param](){
shared_me->ProcessDrawLineParam(param);
});
}
void ChannelOpenedLineType::ProcessDrawLineParam(std::shared_ptr<LineDataParam> param)
{
size_t clientWidth = param->_clientWidth;
size_t start = param->_index;
size_t size = param->_range;
bool bDrawDot = (size > 0) && (clientWidth / size >= 5);
bool bDrawType2 = (size > 0) && (clientWidth / size >= 1);
int width = clientWidth;
if (width == 0)
return;
param->_color = Color();
if (!bDrawType2)
{
bool firstPoint = true;
for (int i = 0; i < width; i++)
{
size_t mappedIdx = start + size - 1 - i * size / width;
if (mappedIdx >= _ringBuffer->Size())
continue;
int y = (*_ringBuffer)[mappedIdx];
param->_list.push_back(y);
}
}
if (bDrawType2)
{
for (size_t i = 0; i < size; i++)
{
if (i + start >= _ringBuffer->Size())
break;
int y = (*_ringBuffer)[i + start];
param->_list.push_back(y);
}
}
}
std::shared_ptr<SoraDbgPlot::Task::TaskSimple> ChannelOpenedLineType::TaskProcessData(std::shared_ptr<DrawLineParam> param, bool bDrawOrGet)
{
auto SThis = dynamic_pointer_cast<ChannelOpenedLineType, AsyncObject>(shared_from_this());
return make_shared<TaskSimple>(TaskQueue(), [SThis, param, bDrawOrGet](){
SThis->Task_ProcessDrawLineParam(param, bDrawOrGet);
//TRACE1("task process data %d\n", bDrawOrGet ? 1 : 0);
});
}
void ChannelOpenedLineType::DrawUsingSample(bool bUseSample)
{
_drawUsingSample = bUseSample;
}
void ChannelOpenedLineType::ProcessDrawLineParam(std::shared_ptr<DrawLineParam> param, bool bDrawOrGet)
{
auto shared_me = dynamic_pointer_cast<ChannelOpenedLineType, AsyncObject>(shared_from_this());
TaskQueue()->DoTask([shared_me, param, bDrawOrGet](){
shared_me->Task_ProcessDrawLineParam(param, bDrawOrGet);
});
}
void ChannelOpenedLineType::DrawLine(Gdiplus::Graphics * g, const Pen* pen, float x1, float y1, float x2, float y2, float maxY, float minY)
{
float deltaY = y2 - y1;
float deltaX = x2 - x1;
float baseX = x1;
float baseY = y1;
y1 = min(maxY, y1);
y1 = max(minY, y1);
if (deltaY != 0.0)
x1 = (y1 - baseY) * deltaX / deltaY + baseX;
y2 = min(maxY, y2);
y2 = max(minY, y2);
if (deltaY != 0.0)
x2 = (y2 - baseY) * deltaX / deltaY + baseX;
g->DrawLine(pen, x1, y1, x2, y2);
}
void ChannelOpenedLineType::Task_ProcessDrawLineParam(std::shared_ptr<DrawLineParam> param, bool bDrawOrGet)
{
if ( (bDrawOrGet == true) && (param->_bMaxMinInitialized == false) )
return;
CRect rect = param->_rect;
size_t start = IndexToSize(param->_index);
size_t size = RangeToSize(param->_range);
if (bDrawOrGet)
{
this->_latestIndex = start;
this->_range = size;
}
if (bDrawOrGet == false)
{
unsigned long long timestamp;
bool succ = this->IndexToTimestamp(param->_index, timestamp);
if (succ)
{
if (!param->_bTimeStampTaken)
{
param->_timeStamp = timestamp;
param->_bTimeStampTaken = true;
}
else
{
param->_timeStamp = max(param->_timeStamp, timestamp);
}
}
}
bool bDrawDot = (size > 0) && (rect.Width() / size >= 5);
bool bDrawType2 = (size > 0) && (rect.Width() / size >= 1);
int width = rect.Width();
if (width == 0)
return;
Gdiplus::REAL lastDispX, lastDispY;
Gdiplus::Color color;
color.SetFromCOLORREF(this->Color());
Gdiplus::Color colorLine;
if (bDrawDot)
colorLine = Gdiplus::Color(64, color.GetR(), color.GetG(), color.GetB());
else
colorLine = Gdiplus::Color(255, color.GetR(), color.GetG(), color.GetB());
Pen penLine(colorLine);
if (!bDrawType2) // more dots than pixels
{
if (_drawUsingSample)
{
bool firstPoint = true;
for (int i = 0; i < width; i++)
{
size_t mappedIdx = start + size - 1 - i * size / width;
if (mappedIdx >= _ringBuffer->Size())
continue;
int y = (*_ringBuffer)[mappedIdx];
double dataT = ::TransformCoordinate(y, param->_bIsLog);
if (bDrawOrGet)
{
Gdiplus::REAL dataY = this->GetClientY(dataT, rect, param->_dispMaxValue, param->_dispMinValue);
Gdiplus::REAL dataX = (Gdiplus::REAL)(i + rect.left);
if (!firstPoint)
this->DrawLine(param->_g, &penLine, lastDispX, lastDispY, dataX, dataY, (float)rect.bottom, (float)rect.top);
else
firstPoint = false;
lastDispX = dataX;
lastDispY = dataY;
}
else
{
if (!param->_bMaxMinInitialized)
{
param->_dispMaxValue = dataT;
param->_dispMinValue = dataT;
param->_bMaxMinInitialized = true;
}
else
{
param->_dispMaxValue = max(param->_dispMaxValue, dataT);
param->_dispMinValue = min(param->_dispMinValue, dataT);
}
}
}
}
else
{
int rectWidth = max(0, rect.Width() - 1);
float maxValue;
float minValue;
float lastX = -1.0;
float lastY;
bool firstPoint = true;
Gdiplus::REAL dataY;
Gdiplus::REAL dataX;
for (size_t i = 0; i < size; i++)
{
if (i + start >= _ringBuffer->Size())
break;
int y = (*_ringBuffer)[i + start];
double dataT = ::TransformCoordinate(y, param->_bIsLog);
dataY = GetClientY(dataT, rect, param->_dispMaxValue, param->_dispMinValue);
dataX = (Gdiplus::REAL)((size - i - 1) * rectWidth / (size - 1) + rect.left);
if (bDrawOrGet)
{
if (dataX != lastX)
{
if (lastX != -1.0)
{
this->DrawLine(param->_g, &penLine, lastX, minValue, lastX, maxValue, (float)rect.bottom, (float)rect.top);
this->DrawLine(param->_g, &penLine, lastX, lastY, dataX, dataY, (float)rect.bottom, (float)rect.top);
}
maxValue = dataY;
minValue = dataY;
lastX = dataX;
}
else
{
maxValue = max(dataY, maxValue);
minValue = min(dataY, minValue);
}
lastY = dataY;
}
else
{
if (!param->_bMaxMinInitialized)
{
param->_dispMaxValue = dataT;
param->_dispMinValue = dataT;
param->_bMaxMinInitialized = true;
}
else
{
param->_dispMaxValue = max(param->_dispMaxValue, dataT);
param->_dispMinValue = min(param->_dispMinValue, dataT);
}
}
}
if (lastX != -1.0)
{
this->DrawLine(param->_g, &penLine, lastX, minValue, lastX, maxValue, (float)rect.bottom, (float)rect.top);
this->DrawLine(param->_g, &penLine, lastX, lastY, dataX, dataY, (float)rect.bottom, (float)rect.top);
}
}
}
if (bDrawType2)
{
Pen penDot(color, 1.5);
int rectWidth = max(0, rect.Width() - 1);
if (size == 1)
{
if (start < _ringBuffer->Size())
{
int y = (*_ringBuffer)[start];
double dataT = ::TransformCoordinate(y, param->_bIsLog);
if (bDrawOrGet)
{
Gdiplus::REAL dataY = GetClientY(dataT, rect, param->_dispMaxValue, param->_dispMinValue);
Gdiplus::REAL dataX = (Gdiplus::REAL)(rectWidth / 2 + rect.left);
this->DrawDot(param->_g, dataX, dataY, penDot);
}
else
{
if (!param->_bMaxMinInitialized)
{
param->_dispMaxValue = dataT;
param->_dispMinValue = dataT;
param->_bMaxMinInitialized = true;
}
else
{
param->_dispMaxValue = max(param->_dispMaxValue, dataT);
param->_dispMinValue = min(param->_dispMinValue, dataT);
}
}
}
}
else
{
bool firstPoint = true;
for (size_t i = 0; i < size; i++)
{
if (i + start >= _ringBuffer->Size())
break;
int y = (*_ringBuffer)[i + start];
double dataT = ::TransformCoordinate(y, param->_bIsLog);
Gdiplus::REAL dataY = GetClientY(dataT, rect, param->_dispMaxValue, param->_dispMinValue);
Gdiplus::REAL dataX = (Gdiplus::REAL)((size - i - 1) * rectWidth / (size - 1) + rect.left);
if (bDrawDot)
this->DrawDot(param->_g, dataX, dataY, penDot, i == size - 1 ? 1 : 0);
if (bDrawOrGet)
{
if (firstPoint)
{
firstPoint = false;
}
else
{
this->DrawLine(param->_g, &penLine, lastDispX, lastDispY, dataX, dataY, (float)rect.bottom, (float)rect.top);
}
lastDispX = dataX;
lastDispY = dataY;
}
else
{
if (!param->_bMaxMinInitialized)
{
param->_dispMaxValue = dataT;
param->_dispMinValue = dataT;
param->_bMaxMinInitialized = true;
}
else
{
param->_dispMaxValue = max(param->_dispMaxValue, dataT);
param->_dispMinValue = min(param->_dispMinValue, dataT);
}
}
}
}
}
}
Gdiplus::REAL ChannelOpenedLineType::GetClientY(double y, const CRect & clientRect, double dispMaxValue, double dispMinValue)
{
double rangeOld = dispMaxValue - dispMinValue;
int rangeNew = clientRect.bottom - clientRect.top;
return float(clientRect.bottom -
(y - dispMinValue) * rangeNew / rangeOld);
}
void ChannelOpenedLineType::DrawDot(Graphics * g, double x, double y, const Pen & pen, int type)
{
int xx = (int)x;
int yy = (int)y;
switch (type)
{
case 0:
g->DrawLine(&pen, xx - 3, yy, xx + 3, yy);
g->DrawLine(&pen, xx, yy - 3, xx, yy + 3);
break;
case 1:
g->DrawLine(&pen, xx, yy, xx + 3, yy);
g->DrawLine(&pen, xx, yy - 3, xx, yy + 3);
break;
default:
;
}
}
size_t ChannelOpenedLineType::RangeToSize(size_t range)
{
return range;
}
size_t ChannelOpenedLineType::IndexToSize(size_t index)
{
return index;
}

Просмотреть файл

@ -0,0 +1,62 @@
#pragma once
#include "ChannelOpenedFixedLengthType.h"
#include "Event.h"
#include "TaskQueue.h"
#include "TaskSimple.h"
#include "FrameWithSizeFilter.h"
#include "RingBufferWithTimeStamp.h"
struct DrawLineParam
{
Graphics * _g;
bool _bIsLog;
CRect _rect;
double _dispMaxValue;
double _dispMinValue;
size_t _index;
size_t _range;
bool _bMaxMinInitialized;
unsigned long long _timeStamp;
bool _bTimeStampTaken;
};
struct LineInfoTask
{
size_t size;
};
struct LineDataParam
{
size_t _index;
size_t _range;
COLORREF _color;
size_t _clientWidth;
std::list<int> _list;
};
class ChannelOpenedLineType : public ChannelOpenedFixedLengthType<int>
{
public:
ChannelOpenedLineType();
std::shared_ptr<SoraDbgPlot::Task::TaskSimple> LineInfoTask(std::shared_ptr<LineInfoTask>);
std::shared_ptr<SoraDbgPlot::Task::TaskSimple> LineDataTask(std::shared_ptr<LineDataParam>);
void DrawUsingSample(bool bUseSample);
void ProcessDrawLineParam(std::shared_ptr<DrawLineParam> param, bool bDrawOrGet);
std::shared_ptr<SoraDbgPlot::Task::TaskSimple> TaskProcessData(std::shared_ptr<DrawLineParam>, bool bDrawOrGet);
protected:
virtual size_t RangeToSize(size_t range);
virtual size_t IndexToSize(size_t index);
private:
void ProcessDrawLineParam(std::shared_ptr<LineDataParam> param);
void ChannelOpenedLineType::Task_ProcessDrawLineParam(std::shared_ptr<DrawLineParam> param, bool bDrawOrGet);
Gdiplus::REAL GetClientY(double y, const CRect & clientRect, double dispMaxValue, double dispMinValue);
void DrawDot(Graphics * g, double x, double y, const Pen & pen, int type = 0);
void DrawLine(Gdiplus::Graphics * g, const Pen* pen, float x1, float y1, float x2, float y2, float maxY, float minY);
bool _drawUsingSample;
};

Просмотреть файл

@ -0,0 +1,169 @@
#include "stdafx.h"
#include <iostream>
#include <sstream>
#include <ostream>
#include "ChannelOpenedLog.h"
#include "LogWithFileBackup.h"
using namespace std;
using namespace SoraDbgPlot::Task;
int ChannelOpenedLog::logObjIdx = 0;
ChannelOpenedLog::ChannelOpenedLog()
{
int logObjIdx = ChannelOpenedLog::logObjIdx++;
_color = RGB(0, 255, 0); // green;
char dir[256];
::GetCurrentDirectoryA(256, dir);
std::ostringstream os;
os << dir << "\\logs\\" << logObjIdx;
ostringstream osName;
osName << logObjIdx;
_logObj = LogWithBackUpFile::Make(os.str().c_str(), osName.str().c_str());
_writeFilter = new SoraDbgPlot::FrameWithSizeInfoWriter<char>();
_writeFilter->EventFlushData.Subscribe([this](const void * sender, const SoraDbgPlot::FrameWithSizeInfoWriter<char>::FlushDataEvent & e){
if (this->_logObj == 0)
return;
size_t dataLen = e.length;
if (dataLen >= 0)
{
int sizeNeeded = dataLen*2 + 1;
char * dataBuf = _newLineFilterBuffer.UseBuf(sizeNeeded);
char * ptrSrc = e.ptr;
char * ptrDest = dataBuf;
char preChar;
while(ptrSrc < e.ptr + e.length)
{
char c = *ptrSrc;
if (c != '\n')
*ptrDest++ = c;
else
{
if ( (ptrSrc == e.ptr) || preChar != '\r')
{
*ptrDest++ = '\r';
*ptrDest++ = '\n';
}
}
ptrSrc++;
preChar = c;
}
*ptrDest = 0;
this->_logObj->AddRecord(dataBuf);
_newLineFilterBuffer.ReturnBuf();
}
});
_newLineFilterBuffer.ConfigKeptSize(16*1024);
}
ChannelOpenedLog::~ChannelOpenedLog()
{
delete _writeFilter;
if (_logObj)
delete _logObj;
}
void ChannelOpenedLog::WriteData(const char * data, size_t length)
{
size_t sizeDummy;
this->_writeFilter->Write(data, length, sizeDummy);
delete [] data;
}
size_t ChannelOpenedLog::DataSize()
{
if (_logObj)
return _logObj->RecordCount();
else
return 1;
}
char * ChannelOpenedLog::GetData(size_t index, bool bFromOldest)
{
char * txt = 0;
auto SThis = dynamic_pointer_cast<ChannelOpenedLog, AsyncObject>(shared_from_this());
TaskQueue()->DoTask([SThis, index, bFromOldest, &txt](){
if (SThis->_logObj)
{
size_t size = SThis->_logObj->RecordCount();
if (size <= index)
return;
size_t index2 = bFromOldest ? index : size - 1 - index;
txt = SThis->_logObj->Record(index2);
}
else
{
txt = "Error creating log file.";
}
});
return txt;
}
shared_ptr<TaskSimple> ChannelOpenedLog::TaskGetSize(shared_ptr<size_t> size)
{
auto SThis = dynamic_pointer_cast<ChannelOpenedLog, AsyncObject>(shared_from_this());
auto task = make_shared<TaskSimple>(TaskQueue(), [SThis, size](){
if (SThis->_logObj)
*size = SThis->_logObj->RecordCount();
else
*size = 1;
});
return task;
}
const wchar_t * ChannelOpenedLog::GetTypeName()
{
return L"Log Channel";
}
bool ChannelOpenedLog::Export(const CString & filename, bool bAll)
{
auto SThis = dynamic_pointer_cast<ChannelOpenedLog, AsyncObject>(shared_from_this());
this->DoLater([SThis, filename, bAll](){
if (SThis->_logObj)
SThis->_logObj->Export(filename);
else
{
auto hfileOutput = ::CreateFileW(
filename,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (hfileOutput != INVALID_HANDLE_VALUE)
CloseHandle(hfileOutput);
}
});
return true;
}
void ChannelOpenedLog::ClearData()
{
if (this->_logObj)
this->_logObj->ClearData();
}

Просмотреть файл

@ -0,0 +1,35 @@
#pragma once
#include <memory>
#include "ChannelOpenedTextType.h"
#include "FrameWithSizeFilter.h"
#include "ILog.h"
#include "TaskSimple.h"
#include "TempBuffer.h"
class ChannelOpenedLog : public ChannelOpenedTextType
{
private:
static int logObjIdx;
public:
ChannelOpenedLog();
~ChannelOpenedLog();
virtual std::shared_ptr<SoraDbgPlot::Task::TaskSimple> TaskGetSize(std::shared_ptr<size_t>);
virtual const wchar_t * GetTypeName();
virtual bool Export(const CString &, bool bAll);
protected:
virtual void WriteData(const char * data, size_t length);
virtual size_t DataSize();
virtual char * GetData(size_t index, bool bFromOldest);
virtual void ClearData();
private:
ILog * _logObj;
COLORREF _color;
SoraDbgPlot::FrameWithSizeInfoWriter<char> * _writeFilter;
SoraDbgPlot::Buffer::TempBuffer _newLineFilterBuffer;
};

Просмотреть файл

@ -0,0 +1,109 @@
#include "stdafx.h"
#include <assert.h>
#include <memory>
#include "ChannelOpenedSpectrum.h"
#include "TaskQueue.h"
using namespace std;
using namespace SoraDbgPlot::Task;
ChannelOpenedSpectrum::ChannelOpenedSpectrum()
{
DrawUsingSample(false);
}
shared_ptr<BaseProperty> ChannelOpenedSpectrum::CreatePropertyPage()
{
return ChannelOpened::CreatePropertyPage();
}
size_t ChannelOpenedSpectrum::RangeToSize(size_t range)
{
return this->_spectrumSize;
}
size_t ChannelOpenedSpectrum::IndexToSize(size_t index)
{
return index * this->_spectrumSize;
}
shared_ptr<TaskSimple> ChannelOpenedSpectrum::TaskUpdateDataSize(std::shared_ptr<size_t> size)
{
auto SThis = dynamic_pointer_cast<ChannelOpenedSpectrum, AsyncObject>(shared_from_this());
return make_shared<TaskSimple>(TaskQueue(), [SThis, size](){
size_t oldSize = *size;
size_t mySize = SThis->_ringBuffer->Size() / SThis->_spectrumSize;
size_t newSize = min(oldSize, mySize);
*size = newSize;
});
}
const wchar_t * ChannelOpenedSpectrum::GetTypeName()
{
return L"Spectrum Channel";
}
bool ChannelOpenedSpectrum::Export(const CString & filename, bool bAll)
{
auto SThis = dynamic_pointer_cast<ChannelOpenedSpectrum, AsyncObject>(shared_from_this());
this->DoLater([SThis, filename, bAll](){
FILE * fp;
errno_t ret = _wfopen_s(&fp, filename, L"wb");
if (ret == 0)
{
size_t spectrumSize = SThis->SpectrumDataSize();
char * digitBuf = new char[128];
//int * numBuf = new int[spectrumSize];
size_t numOutput = 0;
if (bAll)
{
SThis->_ringBuffer->Export([fp, digitBuf, &numOutput, spectrumSize](const int * ptr, size_t length){
while(length > 0)
{
fprintf(fp, "%d ", *ptr);
numOutput++;
if (numOutput == spectrumSize)
{
fprintf(fp, "\r\n");
numOutput = 0;
}
ptr++;
length --;
}
});
}
else
{
size_t start = SThis->_latestIndex;
size_t length = SThis->_range;
length = min(length, SThis->_ringBuffer->Size());
SThis->_ringBuffer->ExportRange(start, length, [fp, digitBuf, &numOutput, spectrumSize](const int * ptr, size_t length){
while(length > 0)
{
fprintf(fp, "%d ", *ptr);
numOutput++;
if (numOutput == spectrumSize)
{
fprintf(fp, "\r\n");
numOutput = 0;
}
ptr++;
length --;
}
});
}
delete [] digitBuf;
fclose(fp);
}
});
return true;
}

Просмотреть файл

@ -0,0 +1,17 @@
#pragma once
#include "ChannelOpenedLineType.h"
#include "TaskQueue.h"
class ChannelOpenedSpectrum : public ChannelOpenedLineType
{
public:
ChannelOpenedSpectrum();
virtual std::shared_ptr<BaseProperty> CreatePropertyPage();
virtual std::shared_ptr<SoraDbgPlot::Task::TaskSimple> TaskUpdateDataSize(std::shared_ptr<size_t>);
virtual const wchar_t * GetTypeName();
virtual bool Export(const CString &, bool bAll);
protected:
virtual size_t RangeToSize(size_t range);
virtual size_t IndexToSize(size_t index);
};

Просмотреть файл

@ -0,0 +1,330 @@
#include "stdafx.h"
#include "ChannelOpenedText.h"
#include "SubPlotWnd.h"
#include "HelperFunc.h"
#include "AppSettings.h"
using namespace std;
using namespace SoraDbgPlot::Task;
ChannelOpenedText::ChannelOpenedText()
{
_plotWnd = 0;
_latestTimeIdx = 0;
_ringBuffer = new RingBufferWithTimeStamp<char>(::SettingGetReplayBufferSize() / sizeof(char));
_filter = new SoraDbgPlot::FrameWithSizeInfoWriter<char>();
_rect = CRect(0, 0, 10, 10);
_filter->EventFlushData.Subscribe([this](const void * sender, const SoraDbgPlot::FrameWithSizeInfoWriter<char>::FlushDataEvent & e){
size_t dataLen = e.length;
if (dataLen >= 0)
{
int sizeNeeded = dataLen*2 + 1;
char * dataBuf = _newLineFilterBuffer.UseBuf(sizeNeeded);
char * ptrSrc = e.ptr;
char * ptrDest = dataBuf;
char preChar;
while(ptrSrc < e.ptr + e.length)
{
char c = *ptrSrc;
if (c != '\n')
*ptrDest++ = c;
else
{
if ( (ptrSrc == e.ptr) || preChar != '\r')
{
*ptrDest++ = '\r';
*ptrDest++ = '\n';
}
}
ptrSrc++;
preChar = c;
}
*ptrDest = 0;
int length = ptrDest - dataBuf;
this->_ringBuffer->Write(dataBuf, length, e.timestamp);
_newLineFilterBuffer.ReturnBuf();
}
});
_newLineFilterBuffer.ConfigKeptSize(16*1024);
}
ChannelOpenedText::~ChannelOpenedText()
{
delete _filter;
delete _ringBuffer;
}
void ChannelOpenedText::WriteData(const char * data, size_t length)
{
size_t dummy;
this->_filter->Write(data, length, dummy);
delete [] data;
}
SubPlotWnd * ChannelOpenedText::CreateSubPlotWnd()
{
auto subWnd = new SubPlotWnd;
auto SThis = dynamic_pointer_cast<ChannelOpenedText, AsyncObject>(shared_from_this());
subWnd->EventMoveWindow.Subscribe([SThis](const void * sender, const CRect & rect){
SThis->_rect = rect;
});
subWnd->EventClosed.Subscribe([SThis](const void * sender, const bool & e){
auto SThis2 = SThis;
SubPlotWnd * subPlotWnd = (SubPlotWnd *)sender;
SThis2->DoLater([SThis2, subPlotWnd](){
if (SThis2->_plotWnd == subPlotWnd)
SThis2->_plotWnd = 0;
auto subPlotWnd2 = subPlotWnd;
SThis2->DoLater([subPlotWnd2](){
delete subPlotWnd2;
});
});
});
this->DoNow([SThis, subWnd](){
subWnd->SetColor(SThis->_color);
SThis->_plotWnd = subWnd;
});
return subWnd;
}
void ChannelOpenedText::SetRect(const CRect & rect)
{
auto shared_me = dynamic_pointer_cast<ChannelOpenedText, AsyncObject>(shared_from_this());
TaskQueue()->QueueTask([shared_me, rect](){
shared_me->_rect = rect;
});
}
std::shared_ptr<SoraDbgPlot::Task::TaskSimple> ChannelOpenedText::TaskGetSize(std::shared_ptr<size_t> size)
{
auto SThis = dynamic_pointer_cast<ChannelOpenedText, AsyncObject>(shared_from_this());
auto task = make_shared<TaskSimple>(TaskQueue(), [SThis, size](){
*size = SThis->_ringBuffer->RecordCount();
});
return task;
}
size_t ChannelOpenedText::DataSize()
{
return this->_ringBuffer->RecordCount();
}
char * ChannelOpenedText::GetData(size_t index, bool bFromOldest)
{
char * addr = 0;
auto SThis = dynamic_pointer_cast<ChannelOpenedText, AsyncObject>(shared_from_this());
TaskQueue()->DoTask([SThis, &addr, index, bFromOldest](){
size_t dataSize = SThis->DataSize();
if (dataSize <= index || index < 0)
{
addr = new char[1];
addr[0] = 0;
return;
}
int index2 = bFromOldest ? dataSize - index - 1 : index;
size_t sizeOfData;
bool succ = SThis->_ringBuffer->GetDataSizeByTimeStampIdx(index2, sizeOfData);
if (succ)
{
char * data = new char[sizeOfData + 1];
size_t readSize;
succ = SThis->_ringBuffer->ReadDataByTimeStampIdx(index2, data, sizeOfData, readSize);
if (succ)
{
data[readSize] = 0;
addr = data;
return;
}
else
{
assert(FALSE);
delete [] data;
return;
}
}
});
return addr;
}
void ChannelOpenedText::CloseSubPlotWnd()
{
auto SThis = dynamic_pointer_cast<ChannelOpenedText, AsyncObject>(shared_from_this());
this->DoLater([SThis](){
if (SThis->_plotWnd)
{
HWND hWnd = SThis->_plotWnd->m_hWnd;
if (hWnd)
::PostMessage(hWnd, WM_CLOSE, 0, 0);
}
});
}
void ChannelOpenedText::SeekTimeStamp(unsigned long long timestamp)
{
auto SThis = dynamic_pointer_cast<ChannelOpenedText, AsyncObject>(shared_from_this());
this->DoLater([SThis, timestamp](){
if (SThis->DataSize() > 0)
{
unsigned long long out;
size_t outIdx;
bool found = SThis->_ringBuffer->GetNearestOldTimeStamp(timestamp, out, outIdx);
if (found)
SThis->_latestTimeIdx = outIdx;
}
});
}
void ChannelOpenedText::UpdateSubPlotWnd()
{
auto SThis = dynamic_pointer_cast<ChannelOpenedText, AsyncObject>(shared_from_this());
this->DoLater([SThis](){
if (SThis->_plotWnd)
{
if (SThis->DataSize() > 0)
{
char * data = SThis->GetData(SThis->_latestTimeIdx, false);
CString str(data);
SThis->_plotWnd->PlotText(str);
delete [] data;
}
}
});
}
void ChannelOpenedText::GetRect(CRect & rect)
{
this->DoNow([this, &rect]() mutable {
rect = this->_rect;
});
}
void ChannelOpenedText::OnColorUpdated()
{
ChannelOpenedTextType::OnColorUpdated();
auto SThis = dynamic_pointer_cast<ChannelOpenedText, AsyncObject>(shared_from_this());
this->DoNow([SThis](){
if (SThis->_plotWnd)
{
SThis->_plotWnd->SetColor(SThis->_color);
}
});
}
HRESULT ChannelOpenedText::AppendXmlProperty(IXMLDOMDocument *pDom, IXMLDOMElement *pParent)
{
ChannelOpened::AppendXmlProperty(pDom, pParent);
auto SThis = dynamic_pointer_cast<ChannelOpenedText, AsyncObject>(shared_from_this());
this->DoNow([SThis, pDom, pParent](){
IXMLDOMElement *pElement = NULL;
CreateAndAddElementNode(pDom, L"subRectTLX", L"\n\t\t\t", pParent, &pElement);
pElement->put_text((_bstr_t)SThis->_rect.TopLeft().x);
CreateAndAddElementNode(pDom, L"subRectTLY", L"\n\t\t\t", pParent, &pElement);
pElement->put_text((_bstr_t)SThis->_rect.TopLeft().y);
CreateAndAddElementNode(pDom, L"subRectBRX", L"\n\t\t\t", pParent, &pElement);
pElement->put_text((_bstr_t)SThis->_rect.BottomRight().x);
CreateAndAddElementNode(pDom, L"subRectBRY", L"\n\t\t\t", pParent, &pElement);
pElement->put_text((_bstr_t)SThis->_rect.BottomRight().y);
});
return S_OK;
}
HRESULT ChannelOpenedText::LoadXmlElement(MSXML2::IXMLDOMNodePtr pElement)
{
ChannelOpened::LoadXmlElement(pElement);
CString cs;
MSXML2::IXMLDOMNodePtr pNode;
pNode = pElement->selectSingleNode(L"subRectTLX");
if (pNode == 0)
goto RET;
int tlx = atoi((LPCSTR)(pNode->text));
pNode = pElement->selectSingleNode(L"subRectTLY");
if (pNode == 0)
goto RET;
int tly =atoi((LPCSTR)(pNode->text));
pNode = pElement->selectSingleNode(L"subRectBRX");
if (pNode == 0)
goto RET;
int brx =atoi((LPCSTR)(pNode->text));
pNode = pElement->selectSingleNode(L"subRectBRY");
if (pNode == 0)
goto RET;
int bry = atoi((LPCSTR)(pNode->text));
this->_rect.SetRect(tlx,tly,brx,bry);
RET:
return S_OK;
}
const wchar_t * ChannelOpenedText::GetTypeName()
{
return L"Text Channel";
}
bool ChannelOpenedText::Export(const CString & filename, bool bAll)
{
auto SThis = dynamic_pointer_cast<ChannelOpenedText, AsyncObject>(shared_from_this());
this->DoLater([SThis, filename, bAll](){
FILE * fp;
errno_t ret = _wfopen_s(&fp, filename, L"wb");
if (ret == 0)
{
if (1)
{
SThis->_ringBuffer->Export([fp](const char * ptr, size_t length){
fwrite(ptr, 1, length, fp);
});
}
fclose(fp);
}
});
return true;
}
void ChannelOpenedText::ClearData()
{
this->_ringBuffer->Reset();
}

Просмотреть файл

@ -0,0 +1,45 @@
#pragma once
#include <memory>
#include "TaskQueue.h"
#include "ChannelOpenedTextType.h"
#include "SubPlotWnd.h"
#include "FrameWithSizeFilter.h"
#include "RingBufferWithTimeStamp.h"
#include "TempBuffer.h"
class ChannelOpenedText : public ChannelOpenedTextType
{
public:
ChannelOpenedText();
~ChannelOpenedText();
void SetRect(const CRect & rect);
SubPlotWnd * ChannelOpenedText::CreateSubPlotWnd();
void CloseSubPlotWnd();
void UpdateSubPlotWnd();
void SeekTimeStamp(unsigned long long timestamp);
virtual HRESULT AppendXmlProperty(IXMLDOMDocument *pDom, IXMLDOMElement *pParent);
virtual HRESULT LoadXmlElement(MSXML2::IXMLDOMNodePtr pElement);
virtual void GetRect(CRect & rect);
virtual const wchar_t * GetTypeName();
virtual bool Export(const CString &, bool bAll);
//virtual void CloseChannel();
protected:
virtual void WriteData(const char * data, size_t length);
virtual std::shared_ptr<SoraDbgPlot::Task::TaskSimple> TaskGetSize(std::shared_ptr<size_t>);
virtual size_t DataSize();
virtual char * GetData(size_t index, bool bFromOldest);
virtual void OnColorUpdated();
virtual void ClearData();
private:
SoraDbgPlot::FrameWithSizeInfoWriter<char> * _filter;
RingBufferWithTimeStamp<char> * _ringBuffer;
SubPlotWnd * _plotWnd;
CRect _rect;
size_t _latestTimeIdx;
SoraDbgPlot::Buffer::TempBuffer _newLineFilterBuffer;
};

Просмотреть файл

@ -0,0 +1,33 @@
#include "stdafx.h"
#include "ChannelOpenedTextType.h"
using namespace std;
ChannelOpenedTextType::ChannelOpenedTextType()
{
}
ChannelOpenedTextType::~ChannelOpenedTextType()
{
}
void ChannelOpenedTextType::OnColorUpdated()
{
EventColor.Raise(this, _color);
}
void ChannelOpenedTextType::Clear()
{
EventColor.Reset();
ChannelOpened::Clear();
}
void ChannelOpenedTextType::ForColor(const std::function<void(COLORREF)> & f)
{
auto SThis = dynamic_pointer_cast<ChannelOpenedTextType, AsyncObject>(shared_from_this());
this->DoLater([SThis, f](){
f(SThis->_color);
});
}

Просмотреть файл

@ -0,0 +1,21 @@
#pragma once
#include "ChannelOpened.h"
class ChannelOpenedTextType : public ChannelOpened
{
public:
ChannelOpenedTextType();
~ChannelOpenedTextType();
SoraDbgPlot::Event::Event<COLORREF> EventColor;
void ForColor(const std::function<void(COLORREF)> & f);
virtual void Clear();
virtual void OnColorUpdated();
virtual std::shared_ptr<SoraDbgPlot::Task::TaskSimple> TaskGetSize(std::shared_ptr<size_t>) = 0;
virtual size_t DataSize() = 0;
virtual char * GetData(size_t index, bool bFromOldest) = 0;
};

Просмотреть файл

@ -0,0 +1,79 @@
// ChannelProperty.cpp : implementation file
//
#include "stdafx.h"
#include "DbgPlotViewer.h"
#include "ChannelProperty.h"
using namespace std;
// ChannelProperty
IMPLEMENT_DYNAMIC(ChannelProperty, BaseProperty)
ChannelProperty::ChannelProperty(const wstring & typeName, const wstring & name, COLORREF color)
{
_typename = typeName;
_name = name;
_color = color;
}
ChannelProperty::~ChannelProperty()
{
}
BEGIN_MESSAGE_MAP(ChannelProperty, BaseProperty)
ON_WM_CREATE()
END_MESSAGE_MAP()
// ChannelProperty message handlers
int ChannelProperty::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (BaseProperty::OnCreate(lpCreateStruct) == -1)
return -1;
CMFCPropertyGridProperty * pProp;
pProp = new CMFCPropertyGridProperty(_T("Type"), _typename.c_str());
pProp->Enable(FALSE);
this->AddProperty(pProp);
pProp = new CMFCPropertyGridProperty(_T("Name"), _name.c_str());
pProp->Enable(FALSE);
this->AddProperty(pProp);
CMFCPropertyGridColorProperty* pColorProp = new CMFCPropertyGridColorProperty(_T("Color"), _color, NULL);
pColorProp->EnableOtherButton(_T("Other..."));
pColorProp->EnableAutomaticButton(_T("Default"), ::GetSysColor(COLOR_3DFACE));
this->AddProperty(pColorProp);
return 0;
}
void ChannelProperty::OnPropertyChanged(CMFCPropertyGridProperty* pProp) const
{
// TODO: Add your specialized code here and/or call the base class
if (wcscmp(pProp->GetName(), L"Color") == 0)
{
COLORREF color = ((CMFCPropertyGridColorProperty *)pProp)->GetColor();
EventColor.Raise(0, color);
}
else
{
ASSERT(false); // impossible
}
return BaseProperty::OnPropertyChanged(pProp);
}
void ChannelProperty::OnCloseProperty()
{
EventColor.Reset();
}

Просмотреть файл

@ -0,0 +1,36 @@
#pragma once
#include "BaseProperty.h"
#include "Event.h"
// ChannelProperty
class ChannelProperty : public BaseProperty
{
DECLARE_DYNAMIC(ChannelProperty)
public:
ChannelProperty(const std::wstring &, const std::wstring &, COLORREF);
virtual ~ChannelProperty();
protected:
virtual void OnCloseProperty();
protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
virtual void OnPropertyChanged(CMFCPropertyGridProperty* pProp) const;
public:
void SetColor(COLORREF color);
SoraDbgPlot::Event::Event<COLORREF> EventColor;
private:
std::wstring _typename;
std::wstring _name;
COLORREF _color;
};

Просмотреть файл

@ -0,0 +1,418 @@
// ChannelTreeCtrl.cpp : implementation file
//
#include "stdafx.h"
#include <memory>
#include "DbgPlotViewer.h"
#include "ChannelTreeCtrl.h"
#include "ChannelOpened.h"
#include "ChannelOpenedLine.h"
#include "ChannelOpenedDots.h"
#include "ChannelOpenedLog.h"
#include "ChannelOpenedText.h"
#include "ChannelOpenedSpectrum.h"
#include "PlotWnd.h"
#include "ChannelAddable.h"
#include "Targetable.h"
using namespace std;
// ChannelTreeCtrl
IMPLEMENT_DYNAMIC(ChannelTreeCtrl, CTreeCtrl)
ChannelTreeCtrl::ChannelTreeCtrl()
{
_bDragging = false;
}
ChannelTreeCtrl::~ChannelTreeCtrl()
{
_pvTaskQueue.Execute(true);
}
void ChannelTreeCtrl::UpdateTreeData(const std::map<std::shared_ptr<ProcessOpened>, std::set<std::shared_ptr<ChannelOpened> > > & tree)
{
_pvTaskQueue.Queue([this, tree](bool bClose){
if (bClose)
return;
this->_processChannelTree = tree;
this->UpdateTreeView();
});
HWND hWnd = m_hWnd;
if (hWnd)
::PostMessage(hWnd, WMME_EXE_TASKQUEUE, 0, 0);
}
void ChannelTreeCtrl::UpdateTreeView()
{
this->SetRedraw(FALSE);
this->DeleteAllItems();
for (auto iterPsChMap = _processChannelTree.begin(); iterPsChMap != _processChannelTree.end(); ++iterPsChMap)
{
auto process = iterPsChMap->first;
CString str;
str.Format(L"%s(%d)", process->Name().c_str(), process->Pid());
int imgIdx = true ? 10 : 11;
HTREEITEM hProcess = this->InsertItem(TVIF_TEXT | TVIF_PARAM | TVIF_IMAGE| TVIF_SELECTEDIMAGE | TVIF_STATE, str.GetBuffer(), imgIdx, imgIdx, 0, 0, (LPARAM)process.get(), 0, TVI_SORT);
auto channelMap = iterPsChMap->second;
for (auto iterChannel = channelMap.begin(); iterChannel != channelMap.end(); ++iterChannel)
{
auto channel = *iterChannel;
CString str;
str.Format(L"%s", channel->Name().c_str());
int imgIdx = 0;
if (typeid(*channel) == typeid(ChannelOpenedLine))
imgIdx = 0;
else if (typeid(*channel) == typeid(ChannelOpenedDots))
imgIdx = 2;
else if (typeid(*channel) == typeid(ChannelOpenedSpectrum))
imgIdx = 4;
else if (typeid(*channel) == typeid(ChannelOpenedLog))
imgIdx = 6;
else if (typeid(*channel) == typeid(ChannelOpenedText))
imgIdx = 8;
if (! channel->IsAttatched())
imgIdx++;
HTREEITEM hItem = this->InsertItem(TVIF_TEXT | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_STATE, str.GetBuffer(), imgIdx, imgIdx, 0, 0, (LPARAM)channel.get(), hProcess, TVI_SORT);
}
this->Expand(hProcess, TVE_EXPAND);
}
this->SetRedraw(TRUE);
}
BEGIN_MESSAGE_MAP(ChannelTreeCtrl, CTreeCtrl)
ON_NOTIFY_REFLECT(TVN_BEGINDRAG, &ChannelTreeCtrl::OnTvnBegindrag)
ON_WM_MOUSEMOVE()
ON_WM_CLOSE()
ON_MESSAGE(WMME_EXE_TASKQUEUE, OnExeTaskQueue)
ON_WM_LBUTTONUP()
ON_NOTIFY_REFLECT(NM_CLICK, &ChannelTreeCtrl::OnNMClick)
ON_WM_CONTEXTMENU()
ON_NOTIFY_REFLECT(NM_RCLICK, &ChannelTreeCtrl::OnNMRClick)
ON_COMMAND(ID_CLOSE_CHANNEL, OnCloseChannel)
ON_COMMAND(ID_CHANNEL_SAVESELECTION, OnChannelSaveSelection)
ON_COMMAND(ID_CHANNEL_SAVEALL, OnChannelSaveAll)
ON_COMMAND(ID_CHANNEL_CLOSE, OnTextChannelClose)
ON_COMMAND(ID_CHANNEL_EXPORT, OnTextChannelExport)
END_MESSAGE_MAP()
// ChannelTreeCtrl message handlers
void ChannelTreeCtrl::OnTvnBegindrag(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
// TODO: Add your control notification handler code here
auto obj = (PropObject *)pNMTreeView->itemNew.lParam;
this->SelectItem(pNMTreeView->itemNew.hItem);
auto spObj = obj->shared_from_this();
auto channel = dynamic_pointer_cast<ChannelOpened, AsyncObject>(spObj);
if (channel && channel->IsAttatched())
{
TRACE0("Channel dragged\n");
SetCapture();
_bDragging = true;
_channelDragged = channel;
}
*pResult = 0;
}
void ChannelTreeCtrl::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if (_bDragging)
{
CPoint pointParam;
auto obj = FindTarget(pointParam);
if (obj != _lastObj)
{
if (_lastObj)
_lastObj->Highlight(false);
_lastObj = obj;
}
if (obj)
{
::SetCursor(::LoadCursor(NULL, IDC_ARROW));
obj->Highlight(true);
}
else
{
::SetCursor(::LoadCursor(NULL, IDC_NO));
}
}
CTreeCtrl::OnMouseMove(nFlags, point);
}
void ChannelTreeCtrl::OnClose()
{
// TODO: Add your message handler code here and/or call default
//_pvTaskQueue.Execute(true);
CTreeCtrl::OnClose();
}
LRESULT ChannelTreeCtrl::OnExeTaskQueue(WPARAM wParam, LPARAM lParam)
{
_pvTaskQueue.Execute(false);
return 0;
}
shared_ptr<ChannelAddable> ChannelTreeCtrl::FindTarget(CPoint & pointOut)
{
CPoint screenCursorPoint;
GetCursorPos(&screenCursorPoint);
CWnd * wnd = WindowFromPoint(screenCursorPoint);
DWORD processId;
::GetWindowThreadProcessId(wnd->GetSafeHwnd(), &processId);
if ( processId != ::GetProcessId(::GetCurrentProcess()) )
{
return false;
}
auto targetable = dynamic_cast<Targetable *>(wnd);
if (targetable)
{
auto channelAddable = (ChannelAddable *)targetable->UserData();
ASSERT(channelAddable);
if (channelAddable->Accept(_channelDragged, screenCursorPoint, pointOut))
return dynamic_pointer_cast<ChannelAddable, AsyncObject>(channelAddable->shared_from_this());
else
return 0;
}
return 0;
}
void ChannelTreeCtrl::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if (_bDragging)
{
CPoint pointOut;
auto obj = this->FindTarget(pointOut);
if (obj)
{
obj->Highlight(false);
if (_channelDragged->IsAttatched())
{
shared_ptr<ProcessOpened> processOpened;
for (auto iterPs = _processChannelTree.begin(); iterPs != _processChannelTree.end(); ++iterPs)
{
auto process = iterPs->first;
auto chMap = iterPs->second;
auto iterCh = chMap.find(_channelDragged);
if (iterCh != chMap.end())
{
processOpened = iterPs->first;
break;
}
}
ASSERT(processOpened != 0);
obj->RequestAddChannel(processOpened, _channelDragged, pointOut);
}
}
ReleaseCapture();
_lastObj = 0;
_bDragging = false;
}
CTreeCtrl::OnLButtonUp(nFlags, point);
}
void ChannelTreeCtrl::PostNcDestroy()
{
// TODO: Add your specialized code here and/or call the base class
_pvTaskQueue.Execute(true);
EventObjSelected.Reset();
EventCloseChannel.Reset();
EventClosed.Raise(this, true);
CTreeCtrl::PostNcDestroy();
}
void ChannelTreeCtrl::OnNMClick(NMHDR *pNMHDR, LRESULT *pResult)
{
DWORD dw = GetMessagePos(); // Mouse position
CPoint p(GET_X_LPARAM(dw), GET_Y_LPARAM(dw));
this->ScreenToClient(&p);
UINT htFlags = 0;
HTREEITEM hHitItem= this->HitTest(p, &htFlags);
if (htFlags & TVHT_ONITEM)
{
auto obj = (PropObject *)this->GetItemData(hHitItem);
auto spObj = dynamic_pointer_cast<PropObject, AsyncObject>(obj->shared_from_this());
this->EventObjSelected.Raise(this, spObj);
}
*pResult = 0;
}
bool ChannelTreeCtrl::ShowFileDialog(CString & filename)
{
CFileDialog dlgFile(FALSE, L"txt", 0, 6UL, L"Text file(*.txt)\0*.txt\0All file(*.*)\0*.*\0\0");
CString fileName;
const int c_cMaxFiles = 100;
const int c_cbBuffSize = (c_cMaxFiles * (MAX_PATH + 1)) + 1;
dlgFile.GetOFN().lpstrFile = fileName.GetBuffer(c_cbBuffSize);
dlgFile.GetOFN().nMaxFile = c_cbBuffSize;
if (IDOK == dlgFile.DoModal())
{
FILE * fp;
errno_t ret = _wfopen_s(&fp, fileName, L"wb");
bool completeBlock = true;
if (ret == 0)
{
fclose(fp);
filename = fileName;
return true;
}
else
{
CString errMsg;
errMsg.Format(L"Open file error: %x\n", ret);
::AfxMessageBox(errMsg);
return false;
}
}
return false;
}
void ChannelTreeCtrl::OnContextMenu(CWnd* /*pWnd*/, CPoint point)
{
bool bOpened = _contextMenuObj->GetOpenState();
if (!bOpened)
return;
auto channelText = dynamic_pointer_cast<ChannelOpenedText, PropObject>(_contextMenuObj);
if (channelText)
{
theApp.GetContextMenuManager()->ShowPopupMenu(IDR_POPUP_TEXT_CHANNEL, point.x, point.y, this, TRUE);
return;
}
auto channelLog = dynamic_pointer_cast<ChannelOpenedLog, PropObject>(_contextMenuObj);
if (channelLog)
{
theApp.GetContextMenuManager()->ShowPopupMenu(IDR_POPUP_TEXT_CHANNEL, point.x, point.y, this, TRUE);
return;
}
auto channel = dynamic_pointer_cast<ChannelOpened, PropObject>(_contextMenuObj);
if (channel)
{
theApp.GetContextMenuManager()->ShowPopupMenu(IDR_POPUP_CHANNEL_EXPLORER, point.x, point.y, this, TRUE);
}
}
void ChannelTreeCtrl::OnNMRClick(NMHDR *pNMHDR, LRESULT *pResult)
{
DWORD dw = GetMessagePos(); // Mouse position
CPoint p(GET_X_LPARAM(dw), GET_Y_LPARAM(dw));
this->ScreenToClient(&p);
UINT htFlags = 0;
HTREEITEM hHitItem= this->HitTest(p, &htFlags);
if (htFlags & TVHT_ONITEM)
{
HTREEITEM hItemOld = this->GetSelectedItem();
this->SelectItem(hHitItem);
auto obj = (PropObject *)this->GetItemData(hHitItem);
auto spObj = dynamic_pointer_cast<ChannelOpened, AsyncObject>(obj->shared_from_this());
if (spObj != 0)
{
_contextMenuObj = spObj;
SendMessage(WM_CONTEXTMENU, (WPARAM) m_hWnd, GetMessagePos());
}
}
*pResult = 1;
}
void ChannelTreeCtrl::OnCloseChannel()
{
this->EventCloseChannel.Raise(this, _contextMenuObj);
}
void ChannelTreeCtrl::OnChannelSaveSelection()
{
CString fileName;
bool succ = ShowFileDialog(fileName);
if (succ)
_contextMenuObj->Export(fileName, false);
}
void ChannelTreeCtrl::OnChannelSaveAll()
{
CString fileName;
bool succ = ShowFileDialog(fileName);
if (succ)
_contextMenuObj->Export(fileName, true);
}
void ChannelTreeCtrl::OnTextChannelExport()
{
CString fileName;
bool succ = ShowFileDialog(fileName);
if (succ)
_contextMenuObj->Export(fileName, true);
}
void ChannelTreeCtrl::OnTextChannelClose()
{
this->EventCloseChannel.Raise(this, _contextMenuObj);
}

Просмотреть файл

@ -0,0 +1,69 @@
#pragma once
#include "ChannelOpened.h"
#include "ProcessOpened.h"
#include "PropObject.h"
#include "PassiveTaskQueue.h"
#include "ChannelAddable.h"
#include "Event.h"
// ChannelTreeCtrl
#define WMME_EXE_TASKQUEUE (WM_APP+1)
class ChannelTreeCtrl : public CTreeCtrl
{
DECLARE_DYNAMIC(ChannelTreeCtrl)
public:
ChannelTreeCtrl();
virtual ~ChannelTreeCtrl();
void UpdateTreeData(const std::map<std::shared_ptr<ProcessOpened>, std::set<std::shared_ptr<ChannelOpened> > > & tree);
SoraDbgPlot::Event::Event<bool> EventClosed;
SoraDbgPlot::Event::Event<std::shared_ptr<PropObject> > EventObjSelected;
SoraDbgPlot::Event::Event<std::shared_ptr<ChannelOpened> > EventCloseChannel;
private:
bool ShowFileDialog(CString & filename);
private:
void UpdateTreeView();
std::shared_ptr<ChannelAddable> FindTarget(CPoint & pointOut);
protected:
DECLARE_MESSAGE_MAP()
private:
std::map<std::shared_ptr<ProcessOpened>, std::set<std::shared_ptr<ChannelOpened> > > _processChannelTree;
std::shared_ptr<ChannelOpened> _channelDragged;
bool _bDragging;
std::shared_ptr<ChannelAddable> _lastObj;
std::shared_ptr<ChannelOpened> _contextMenuObj;
void HighlightWindow(CWnd * wnd, bool highlight);
public:
afx_msg void OnTvnBegindrag(NMHDR *pNMHDR, LRESULT *pResult);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg void OnClose();
afx_msg LRESULT OnExeTaskQueue(WPARAM, LPARAM);
private:
PassiveTaskQueue _pvTaskQueue;
public:
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
virtual void PostNcDestroy();
afx_msg void OnNMClick(NMHDR *pNMHDR, LRESULT *pResult);
afx_msg void OnContextMenu(CWnd* /*pWnd*/, CPoint /*point*/);
afx_msg void OnNMRClick(NMHDR *pNMHDR, LRESULT *pResult); afx_msg void OnCloseChannel();
afx_msg void OnChannelSaveSelection();
afx_msg void OnChannelSaveAll();
afx_msg void OnTextChannelExport();
afx_msg void OnTextChannelClose();
};

Просмотреть файл

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<ClassDiagram />

Просмотреть файл

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<ClassDiagram />

Просмотреть файл

@ -0,0 +1,147 @@
#include "stdafx.h"
#include "ControlPanelDriver.h"
using namespace std;
ControlPanelDriver::~ControlPanelDriver()
{
}
std::shared_ptr<CWnd> ControlPanelDriver::GetControlWnd()
{
shared_ptr<CWnd> ret;
auto SThis = dynamic_pointer_cast<ControlPanelDriver, AsyncObject>(shared_from_this());
this->DoNow([SThis, &ret](){
if (SThis->_controlPanelList == 0)
{
SThis->_controlPanelList = make_shared<ControlPanelList>();
}
ret = SThis->_controlPanelList;
});
return ret;
}
void ControlPanelDriver::AddProcessOpened(std::shared_ptr<ProcessOpened> process)
{
auto SThis = dynamic_pointer_cast<ControlPanelDriver, AsyncObject>(shared_from_this());
this->DoLater([SThis, process](){
auto process2 = process;
auto iter = SThis->_processWndMap.find(process);
if (iter == SThis->_processWndMap.end())
{
CString caption;
caption.Format(L"%s(%d)", process2->Name().c_str(), process2->Pid());
auto wnd = make_shared<ControlPanelWnd>(caption);
wnd->EventPlayPause.Subscribe([process2](const void * sender, const bool & bPlayPause){
process2->TraceBarPlayPause(bPlayPause);
});
wnd->EventSingleStep.Subscribe([process2](const void * sender, const bool & dummy){
process2->TraceBarSingleStep();
});
wnd->EventTraceBarSizeChanged.Subscribe([process2](const void * sender, const CRect & rect){
process2->SetBitmapRect(rect);
});
wnd->EventTraceBarWheel.Subscribe([process2](const void * sender, const bool & isUp){
process2->TrackBarWheel(isUp);
});
wnd->EventTraceBarSeek.Subscribe([process2](const void * sender, const double & pos){
process2->TrackBarSeek(pos);
});
auto SThis2 = SThis;
wnd->EventClosed.Subscribe([SThis2, process2](const void * sender, const bool & e){
auto SThis = SThis2;
auto process = process2;
SThis->DoLater([SThis, process](){
auto iter = SThis->_processWndMap.find(process);
assert(process);
auto wnd = iter->second;
SThis->_processWndMap.erase(process);
SThis->_processIsUpdating.erase(process);
if (SThis->_controlPanelList)
{
SThis->_controlPanelList->RemoveControlPanelWnd(wnd);
}
});
});
SThis->_processWndMap.insert(make_pair(process, wnd));
SThis->_processIsUpdating.insert(make_pair(process, false));
if (SThis->_controlPanelList)
{
SThis->_controlPanelList->AddControlPanelWnd(wnd);
}
TRACE1("Process Opened activated %d\n", process->Pid());
}
});
}
void ControlPanelDriver::RemoveProcess(std::shared_ptr<ProcessOpened> process)
{
auto SThis = dynamic_pointer_cast<ControlPanelDriver, AsyncObject>(shared_from_this());
this->DoLater([SThis, process](){
auto iter = SThis->_processWndMap.find(process);
if (iter == SThis->_processWndMap.end())
{
assert(false);
return;
}
auto wnd = iter->second;
HWND hWnd = wnd->m_hWnd;
if (hWnd)
::PostMessage(hWnd, WM_CLOSE, 0, 0);
});
}
void ControlPanelDriver::Update()
{
auto SThis = dynamic_pointer_cast<ControlPanelDriver, AsyncObject>(shared_from_this());
this->DoLater([SThis](){
for (auto iter = SThis->_processWndMap.begin(); iter != SThis->_processWndMap.end(); ++iter)
{
auto process = iter->first;
auto wnd = iter->second;
bool bProcessUpdating = SThis->_processIsUpdating.find(process)->second;
if (bProcessUpdating)
continue;
auto SThis2 = SThis;
process->GenUpdateData([SThis2](Bitmap * bitmap, bool isRawDataBufInUse, shared_ptr<ProcessOpened> process){
auto SThis3 = SThis2;
SThis2->DoLater([SThis3, bitmap, isRawDataBufInUse, process](){
auto iter = SThis3->_processWndMap.find(process);
if (iter != SThis3->_processWndMap.end())
{
auto wnd = iter->second;
wnd->SetBitmap(bitmap);
wnd->EnableButton(isRawDataBufInUse);
}
auto iterUpdate = SThis3->_processIsUpdating.find(process);
if (iterUpdate != SThis3->_processIsUpdating.end())
iterUpdate->second = false;
});
});
}
}, [](){});
}
void ControlPanelDriver::Clear()
{
}

Просмотреть файл

@ -0,0 +1,23 @@
#pragma once
#include <memory>
#include <set>
#include "AsyncObject.h"
#include "ProcessOpened.h"
#include "ControlPanelWnd.h"
#include "ControlPanelList.h"
class ControlPanelDriver : public AsyncObject
{
public:
~ControlPanelDriver();
std::shared_ptr<CWnd> GetControlWnd();
void AddProcessOpened(std::shared_ptr<ProcessOpened>);
void RemoveProcess(std::shared_ptr<ProcessOpened>);
void Update();
void Clear();
private:
std::shared_ptr<ControlPanelList> _controlPanelList;
std::map<std::shared_ptr<ProcessOpened>, std::shared_ptr<ControlPanelWnd> > _processWndMap;
std::map<std::shared_ptr<ProcessOpened>, bool> _processIsUpdating;
};

Просмотреть файл

@ -0,0 +1,131 @@
// ControlPanelList.cpp : implementation file
//
#include "stdafx.h"
#include <algorithm>
#include "DbgPlotViewer.h"
#include "ControlPanelList.h"
// ControlPanelList
IMPLEMENT_DYNAMIC(ControlPanelList, Invokable)
ControlPanelList::ControlPanelList()
{
}
ControlPanelList::~ControlPanelList()
{
}
void ControlPanelList::AddControlPanelWnd(std::shared_ptr<ControlPanelWnd> wnd)
{
this->Invoke([this, wnd](bool close){
if (close)
return;
if (m_hWnd == 0)
return;
this->_controlPanelList.push_back(wnd);
CRect rectDummy;
rectDummy.SetRectEmpty();
wnd->Create(NULL, NULL, WS_CHILD | WS_VISIBLE, rectDummy, this, 0);
if (this->m_hWnd)
this->AdjustLayout();
});
}
void ControlPanelList::RemoveControlPanelWnd(std::shared_ptr<ControlPanelWnd> wnd)
{
this->Invoke([this, wnd](bool close){
if (close)
return;
auto iter = std::find(this->_controlPanelList.begin(), this->_controlPanelList.end(), wnd);
assert(iter != this->_controlPanelList.end());
this->_controlPanelList.erase(iter);
if (this->m_hWnd)
this->AdjustLayout();
});
}
void ControlPanelList::AdjustLayout()
{
CRect rect;
this->GetClientRect(&rect);
int width = rect.Width();
int y = 0;
const int WND_HEIGHT= ControlPanelWnd::Height();
const int MARGIN = 1;
for (
auto iterWnd = _controlPanelList.begin();
iterWnd != _controlPanelList.end();
++iterWnd)
{
auto& wnd = *iterWnd;
if (wnd->m_hWnd)
{
wnd->MoveWindow(0, y, width, WND_HEIGHT, 1);
y += WND_HEIGHT + MARGIN;
}
}
}
BEGIN_MESSAGE_MAP(ControlPanelList, Invokable)
ON_WM_SIZE()
ON_WM_PAINT()
END_MESSAGE_MAP()
// ControlPanelList message handlers
void ControlPanelList::OnSize(UINT nType, int cx, int cy)
{
Invokable::OnSize(nType, cx, cy);
// TODO: Add your message handler code here
this->Invoke([this, cx](bool close){
if (close)
return;
if (this->m_hWnd)
this->AdjustLayout();
});
}
void ControlPanelList::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
// Do not call Invokable::OnPaint() for painting messages
CBrush brush(RGB(0, 0, 0));
CRect rect;
GetClientRect(&rect);
dc.FillRect(rect,&brush);
}
BOOL ControlPanelList::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Add your specialized code here and/or call the base class
cs.style |= WS_CLIPCHILDREN;
return Invokable::PreCreateWindow(cs);
}
void ControlPanelList::PostNcDestroy()
{
// TODO: Add your specialized code here and/or call the base class
Invokable::PostNcDestroy();
}

Просмотреть файл

@ -0,0 +1,37 @@
#pragma once
#include <functional>
#include <vector>
#include "Invokable.h"
#include "ControlPanelWnd.h"
#include "Event.h"
// ControlPanelList
class ControlPanelList : public Invokable
{
DECLARE_DYNAMIC(ControlPanelList)
public:
ControlPanelList();
virtual ~ControlPanelList();
void AddControlPanelWnd(std::shared_ptr<ControlPanelWnd>);
void RemoveControlPanelWnd(std::shared_ptr<ControlPanelWnd>);
private:
void AdjustLayout();
private:
std::list<std::shared_ptr<ControlPanelWnd> > _controlPanelList;
protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnPaint();
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
virtual void PostNcDestroy();
};

Просмотреть файл

@ -0,0 +1,446 @@
// ControlPanelWnd.cpp : implementation file
//
#include "stdafx.h"
#include "DbgPlotViewer.h"
#include "ControlPanelWnd.h"
// ControlPanelWnd
IMPLEMENT_DYNAMIC(ControlPanelWnd, Invokable)
ControlPanelWnd::ControlPanelWnd(const CString & caption)
{
_captionWidth = 100;
_readPos = 0.4f;
_writePos = 0.55f;
_caption = caption;
_buttonIsPlayState = false;
_bitmap = 0;
_buttonEnabled = true;
}
ControlPanelWnd::~ControlPanelWnd()
{
if (_bitmap)
delete _bitmap;
}
int ControlPanelWnd::Height()
{
return 30;
}
int ControlPanelWnd::ButtonWidth()
{
return 28;
}
void ControlPanelWnd::DrawCaption(Graphics * g)
{
SolidBrush fontBrush(Color(255, 150, 150, 150));
StringFormat format;
format.SetAlignment(StringAlignmentNear);
//format.SetFormatFlags(StringFormatFlagsNoWrap);
//format.SetTrimming(StringTrimmingEllipsisCharacter);
Gdiplus::Font captionFont(L"Arial", 10);
PointF pointF(5, 2);
CRect rectCaption;
GetClientRect(&rectCaption);
int top = rectCaption.top;
int bottom = rectCaption.bottom;
int middle = (top + bottom) / 2;
rectCaption.left = this->_captionLeft;
rectCaption.right = this->_captionRight;
SolidBrush brushBk(Color(30, 30, 30));
g->FillRectangle(&brushBk, rectCaption.left, rectCaption.top, rectCaption.right,rectCaption.bottom);
RectF rectName(
(Gdiplus::REAL)this->_captionLeft,
(Gdiplus::REAL)top,
(Gdiplus::REAL)this->_captionRight,
(Gdiplus::REAL)bottom );
g->DrawString(_caption, -1, &captionFont, rectName, &format, &fontBrush);
}
void ControlPanelWnd::DrawTrackBar(Graphics * g)
{
CRect rect;
GetClientRect(&rect);
if (_bitmap)
{
g->DrawImage(_bitmap, _trackBarLeft, rect.top, _trackBarRight - _trackBarLeft, rect.bottom - rect.top);
}
//CRect rect;
//GetClientRect(&rect);
//rect.left = this->_trackBarLeft;
//rect.right = this->_trackBarRight;
//float readRatio = this->_readPos;
//float readPos = (rect.right - rect.left) * readRatio + rect.left;
//Color colorReadDataPart(28,48,69);
//SolidBrush brushReadDataPart(colorReadDataPart);
//g->FillRectangle(
// &brushReadDataPart,
// float(rect.left),
// float(rect.top),
// readPos,
// float(rect.bottom));
//float emptyStartPos = readPos;
//if (this->_readPos < this->_writePos)
//{
// float writeRatio = (float)this->_writePos;
// float writePos = float((rect.right - rect.left) * writeRatio + rect.left);
// Color colorWriteDataPart(100, 100, 100);
// SolidBrush brushWriteDataPart(colorWriteDataPart);
// g->FillRectangle(
// &brushWriteDataPart,
// readPos,
// float(rect.top),
// writePos,
// float(rect.bottom));
// emptyStartPos = writePos;
//}
//SolidBrush brush(Color::Black);
//g->FillRectangle(
// &brush,
// emptyStartPos,
// float(rect.top),
// float(rect.right),
// float(rect.bottom));
}
void ControlPanelWnd::AdjustLayout()
{
// calculate one by one
/*
|caption|trace bar|play button|single step button|
*/
CRect rect;
this->GetClientRect(&rect);
int width = rect.Width();
int height = rect.Height();
const int MARGIN = 1;
const int BUTTON_WIDTH = ControlPanelWnd::ButtonWidth();
_captionLeft = 1;
_captionRight = _captionLeft + _captionWidth;
int buttonWidthRequired = MARGIN * 3 + BUTTON_WIDTH * 2;
if (_captionRight + buttonWidthRequired >= width) // layout buttons from left
{
_trackBarLeft = _trackBarRight = _captionRight;
_playButtonLeft = _captionRight + MARGIN;
_playButtonRight = _playButtonLeft + BUTTON_WIDTH;
_singleStepButtonLeft = _playButtonRight + MARGIN;
_singleStepButtonRight = _singleStepButtonLeft + BUTTON_WIDTH;
}
else // layout buttons from right
{
_singleStepButtonRight = width - MARGIN;
_singleStepButtonLeft = _singleStepButtonRight - BUTTON_WIDTH;
_playButtonRight = _singleStepButtonLeft - MARGIN;
_playButtonLeft = _playButtonRight - BUTTON_WIDTH;
_trackBarLeft = _captionRight + MARGIN;
_trackBarRight = _playButtonLeft - MARGIN;
assert(_trackBarRight >= _trackBarLeft);
}
_playButton.MoveWindow(_playButtonLeft, 0, BUTTON_WIDTH, height, 1);
_singleStepButton.MoveWindow(_singleStepButtonLeft, 0, BUTTON_WIDTH, height, 1);
}
void ControlPanelWnd::SetCaptionWidth(int width)
{
this->Invoke([this, width](bool close){
if (close) return;
this->_captionWidth = width;
});
}
void ControlPanelWnd::SetCaption(const CString & caption)
{
this->Invoke([this, caption](bool close){
if (close) return;
this->_caption = caption;
});
}
void ControlPanelWnd::SetReadWritePos(float readPos, float writePos)
{
this->Invoke([this, readPos, writePos](bool close){
if (close) return;
this->_readPos = readPos;
this->_writePos = writePos;
});
}
void ControlPanelWnd::SetPlayPauseButtonState(bool bPlay)
{
this->Invoke([this, bPlay](bool close){
if (close) return;
this->_buttonIsPlayState = bPlay;
if (_playButton.m_hWnd)
{
if (bPlay)
{
_playButton.SetImage(IDB_BITMAP_CONTROL_PLAY, IDB_BITMAP_CONTROL_PLAY);
}
else
{
_playButton.SetImage(IDB_BITMAP_CONTROL_PAUSE, IDB_BITMAP_CONTROL_PAUSE);
}
_playButton.Invalidate(TRUE);
}
});
}
void ControlPanelWnd::SetBitmap(Bitmap * bitmap)
{
this->Invoke([this, bitmap](bool close){
if (close)
{
delete bitmap;
return;
}
if (_bitmap)
delete _bitmap;
if (this->m_hWnd)
{
_bitmap = bitmap;
this->Invalidate();
}
else
{
delete bitmap;
}
});
}
void ControlPanelWnd::EnableButton(bool bEnable)
{
this->Invoke([this, bEnable](bool close){
if (close) return;
if (_playButton.m_hWnd != 0)
{
if (_buttonEnabled != bEnable)
{
this->_playButton.EnableWindow(bEnable ? TRUE : FALSE);
}
}
if (_singleStepButton.m_hWnd != 0)
{
if (_buttonEnabled != bEnable)
{
this->_singleStepButton.EnableWindow(bEnable ? TRUE : FALSE);
}
}
_buttonEnabled = bEnable;
});
}
BEGIN_MESSAGE_MAP(ControlPanelWnd, Invokable)
ON_WM_SIZE()
ON_WM_CREATE()
ON_WM_PAINT()
ON_COMMAND(ControlPanelWnd::ID_PLAY_BUTTON, &ControlPanelWnd::OnPlayPauseButtonClicked)
ON_COMMAND(ControlPanelWnd::ID_SINGLE_STEP_BUTTON, &ControlPanelWnd::OnSingleStepButtonClicked)
ON_WM_MOUSEWHEEL()
ON_WM_LBUTTONDOWN()
ON_WM_MOUSEMOVE()
END_MESSAGE_MAP()
// ControlPanelWnd message handlers
void ControlPanelWnd::OnSize(UINT nType, int cx, int cy)
{
Invokable::OnSize(nType, cx, cy);
// TODO: Add your message handler code here
this->Invoke([this](bool close){
if (close) return;
if (this->m_hWnd == 0)
return;
this->AdjustLayout();
CRect rect;
this->GetClientRect(&rect);
rect.left = _trackBarLeft;
rect.right = _trackBarRight;
EventTraceBarSizeChanged.Raise(this, rect);
});
}
int ControlPanelWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (Invokable::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
CRect rectDummy;
rectDummy.SetRectEmpty();
//_playButton.m_bTransparent = TRUE;
_playButton.SetImage(IDB_BITMAP_CONTROL_PAUSE, IDB_BITMAP_CONTROL_PAUSE);
_playButton.Create(L"", BS_PUSHBUTTON | BS_OWNERDRAW | WS_VISIBLE | WS_CHILD,
rectDummy, this, ID_PLAY_BUTTON);
_singleStepButton.SetImage(IDB_BITMAP_SINGLESTEP, IDB_BITMAP_SINGLESTEP);
_singleStepButton.Create(L"", BS_PUSHBUTTON | BS_OWNERDRAW | WS_VISIBLE | WS_CHILD,
rectDummy, this, ID_SINGLE_STEP_BUTTON);
return 0;
}
void ControlPanelWnd::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
// Do not call Invokable::OnPaint() for painting messages
//CBrush brush(RGB(0, 0, 0));
CRect rect;
GetClientRect(&rect);
//dc.FillRect(rect,&brush);
Bitmap bmp(rect.right,rect.bottom);
Graphics* memGraph = Graphics::FromImage(&bmp);
SolidBrush brushBg(Color::Black);
memGraph->FillRectangle(
&brushBg,
rect.left,
rect.top,
rect.Width(),
rect.Height()
);
this->DrawCaption(memGraph);
this->DrawTrackBar(memGraph);
Graphics graphics(dc.m_hDC);
graphics.DrawImage(&bmp,rect.left,rect.top,rect.right,rect.bottom);
delete memGraph;
}
BOOL ControlPanelWnd::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Add your specialized code here and/or call the base class
cs.style |= WS_CLIPCHILDREN;
return Invokable::PreCreateWindow(cs);
}
void ControlPanelWnd::OnPlayPauseButtonClicked()
{
EventPlayPause.Raise(this, _buttonIsPlayState);
//_playButton.SetWindowText(_buttonIsPlayState ? L"||" : L">");
if (_playButton.m_hWnd)
{
if (_buttonIsPlayState)
{
_playButton.SetImage(IDB_BITMAP_CONTROL_PAUSE, IDB_BITMAP_CONTROL_PAUSE);
}
else
{
_playButton.SetImage(IDB_BITMAP_CONTROL_PLAY, IDB_BITMAP_CONTROL_PLAY);
}
_playButton.Invalidate(TRUE);
_buttonIsPlayState = !_buttonIsPlayState;
}
}
void ControlPanelWnd::OnSingleStepButtonClicked()
{
EventSingleStep.Raise(this, true);
this->SetPlayPauseButtonState(true);
}
void ControlPanelWnd::PostNcDestroy()
{
// TODO: Add your specialized code here and/or call the base class
EventClosed.Raise(this, true);
EventPlayPause.Reset();
EventSingleStep.Reset();
EventTraceBarSizeChanged.Reset();
EventTraceBarWheel.Reset();
EventTraceBarSeek.Reset();
EventClosed.Reset();
Invokable::PostNcDestroy();
}
BOOL ControlPanelWnd::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
// TODO: Add your message handler code here and/or call default
EventTraceBarWheel.Raise(this, zDelta > 0);
return Invokable::OnMouseWheel(nFlags, zDelta, pt);
}
void ControlPanelWnd::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
int width = _trackBarRight - _trackBarLeft;
if (width > 0)
{
if (point.x >= _trackBarLeft &&
point.y < _trackBarRight)
{
double pos = ((double)(point.x - _trackBarLeft)) / width;
EventTraceBarSeek.Raise(this, pos);
}
}
Invokable::OnLButtonDown(nFlags, point);
}
void ControlPanelWnd::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
SetFocus();
Invokable::OnMouseMove(nFlags, point);
}

Просмотреть файл

@ -0,0 +1,82 @@
#pragma once
#include "Invokable.h"
#include "CustomButton.h"
#include "Event.h"
// ControlPanelWnd
class ControlPanelWnd : public Invokable
{
DECLARE_DYNAMIC(ControlPanelWnd)
public:
static int Height();
static int ButtonWidth();
public:
ControlPanelWnd(const CString &);
virtual ~ControlPanelWnd();
void SetCaptionWidth(int width);
void SetCaption(const CString & caption);
void SetReadWritePos(float readPos, float writePos);
void SetPlayPauseButtonState(bool bPlay);
void SetBitmap(Bitmap * bitmap);
void EnableButton(bool bEnable);
SoraDbgPlot::Event::Event<bool> EventClosed;
SoraDbgPlot::Event::Event<bool> EventPlayPause;
SoraDbgPlot::Event::Event<bool> EventSingleStep;
SoraDbgPlot::Event::Event<CRect> EventTraceBarSizeChanged;
SoraDbgPlot::Event::Event<bool> EventTraceBarWheel;
SoraDbgPlot::Event::Event<double> EventTraceBarSeek;
private:
void AdjustLayout();
void DrawCaption(Graphics * g);
void DrawTrackBar(Graphics * g);
private:
bool _buttonEnabled;
Bitmap * _bitmap;
CString _caption;
float _readPos;
float _writePos;
bool _buttonIsPlayState;
enum {
ID_PLAY_BUTTON = 1,
ID_SINGLE_STEP_BUTTON
};
CFont _buttonFont;
CustomButton _playButton;
CustomButton _singleStepButton;
int _captionWidth;
int _captionLeft;
int _captionRight;
int _trackBarLeft;
int _trackBarRight;
int _playButtonLeft;
int _playButtonRight;
int _singleStepButtonLeft;
int _singleStepButtonRight;
protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnPaint();
afx_msg void OnPlayPauseButtonClicked();
afx_msg void OnSingleStepButtonClicked();
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
virtual void PostNcDestroy();
afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
};

Просмотреть файл

@ -0,0 +1,98 @@
#include "stdafx.h"
#include <DbgHelp.h>
#include "PathName.h"
#define ATOW2(x) L##x
#define ATOW(x) ATOW2(x)
#define __WDATE__ ATOW(__DATE__)
#define __WTIME__ ATOW(__TIME__)
const wchar_t * buildString = __WDATE__ __WTIME__;
static LONG WINAPI AppUnhandledExceptionFilter(
_In_ struct _EXCEPTION_POINTERS *ExceptionInfo
)
{
CString errMsg;
DWORD requiredSize = GetCurrentDirectory(0, NULL);
if (requiredSize == 0) // error, just exit
{
errMsg.Format(L"DbgPlot Viewer has crashed.\n");
::AfxMessageBox(errMsg);
::OutputDebugString(L"DbgPlot Crash dump: error in querying directory 1\n");
return EXCEPTION_CONTINUE_SEARCH;
}
wchar_t * currentPathBuffer = new wchar_t[requiredSize];
DWORD pathLen = GetCurrentDirectory(requiredSize, currentPathBuffer);
if (pathLen != requiredSize - 1) // error
{
delete [] currentPathBuffer;
errMsg.Format(L"DbgPlot Viewer has crashed.\n");
::AfxMessageBox(errMsg);
::OutputDebugString(L"DbgPlot Crash dump: error in querying directory 2\n");
return EXCEPTION_CONTINUE_SEARCH;
}
PathName pathName;
pathName.Append(currentPathBuffer);
delete [] currentPathBuffer;
pathName.Append(L"\\");
pathName.AppendWithEscape(buildString, '_');
FILETIME fileTime;
::GetSystemTimeAsFileTime(&fileTime);
CString time;
time.Format(L"{%d%d}", fileTime.dwHighDateTime, fileTime.dwLowDateTime);
pathName.AppendWithEscape(time, '_');
pathName.Append(L".dmp");
HANDLE hFile = CreateFileW(
(const wchar_t *)pathName,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (hFile == INVALID_HANDLE_VALUE)
{
errMsg.Format(L"DbgPlot Viewer has crashed. Cannot create crash dump file in %s\n", (const wchar_t *)pathName);
::AfxMessageBox(errMsg);
return EXCEPTION_CONTINUE_SEARCH;
}
BOOL succ = ::MiniDumpWriteDump(
GetCurrentProcess(),
GetCurrentProcessId(),
hFile,
MiniDumpNormal,
NULL,
NULL,
NULL);
if (succ == TRUE)
{
errMsg.Format(L"DebugPlot Viewer has crashed. A crash dump file is saved at %s\n", (const wchar_t *)pathName);
::AfxMessageBox(errMsg);
}
else
{
errMsg.Format(L"DebugPlot Viewer has crashed. Error happened in writing dump file to %s\n", (const wchar_t *)pathName);
::AfxMessageBox(errMsg);
}
CloseHandle(hFile);
return EXCEPTION_CONTINUE_SEARCH;
}
void SetCrashDump()
{
::SetUnhandledExceptionFilter(AppUnhandledExceptionFilter);
}

Просмотреть файл

@ -0,0 +1,3 @@
#pragma once
void SetCrashDump();

Просмотреть файл

@ -0,0 +1,30 @@
// CustomButton.cpp : implementation file
//
#include "stdafx.h"
#include "DbgPlotViewer.h"
#include "CustomButton.h"
// CustomButton
IMPLEMENT_DYNAMIC(CustomButton, CMFCButton)
CustomButton::CustomButton()
{
}
CustomButton::~CustomButton()
{
}
BEGIN_MESSAGE_MAP(CustomButton, CMFCButton)
END_MESSAGE_MAP()
// CustomButton message handlers

Просмотреть файл

@ -0,0 +1,18 @@
#pragma once
// CustomButton
class CustomButton : public CMFCButton
{
DECLARE_DYNAMIC(CustomButton)
public:
CustomButton();
virtual ~CustomButton();
protected:
DECLARE_MESSAGE_MAP()
};

Просмотреть файл

@ -0,0 +1,6 @@
#define VER_FILEDESCRIPTION_STR "DebugPlot Viewer"
#define VER_INTERNALNAME_STR "DbgPlot.exe"
#define VER_ORIGINALFILENAME_STR "DbgPlot.exe"
#include "Version.rc"

Просмотреть файл

@ -0,0 +1,675 @@
// DbgPlotViewer.cpp : Defines the class behaviors for the application.
//
#include "stdafx.h"
#include "afxwinappex.h"
#include "afxdialogex.h"
#include "DbgPlotViewer.h"
#include "MainFrm.h"
#include "DbgPlotViewerDoc.h"
#include "DbgPlotViewerView.h"
#include "Event.h"
#include "TaskQueue.h"
#include "SharedNameManagement.h"
#include "CrashDump.h"
using namespace std;
using namespace SoraDbgPlot::SharedObj;
using namespace SoraDbgPlot::Task;
using namespace SoraDbgPlot::Event;
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CDbgPlotViewerApp
BEGIN_MESSAGE_MAP(CDbgPlotViewerApp, CWinAppEx)
ON_COMMAND(ID_APP_ABOUT, &CDbgPlotViewerApp::OnAppAbout)
// Standard file based document commands
ON_COMMAND(ID_FILE_NEW, &CWinAppEx::OnFileNew)
ON_COMMAND(ID_FILE_OPEN, &CWinAppEx::OnFileOpen)
// Standard print setup command
ON_COMMAND(ID_FILE_PRINT_SETUP, &CWinAppEx::OnFilePrintSetup)
END_MESSAGE_MAP()
// CDbgPlotViewerApp construction
CDbgPlotViewerApp::CDbgPlotViewerApp()
{
m_bHiColorIcons = TRUE;
// support Restart Manager
m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_ALL_ASPECTS;
#ifdef _MANAGED
// If the application is built using Common Language Runtime support (/clr):
// 1) This additional setting is needed for Restart Manager support to work properly.
// 2) In your project, you must add a reference to System.Windows.Forms in order to build.
System::Windows::Forms::Application::SetUnhandledExceptionMode(System::Windows::Forms::UnhandledExceptionMode::ThrowException);
#endif
// TODO: replace application ID string below with unique ID string; recommended
// format for string is CompanyName.ProductName.SubProduct.VersionInformation
SetAppID(_T("DbgPlotViewer.AppID.NoVersion"));
// TODO: add construction code here,
// Place all significant initialization in InitInstance
#ifdef ENABLE_CRASH_DUMP
_bEnableCrashDump = true;
#else
_bEnableCrashDump = false;
#endif
}
// The one and only CDbgPlotViewerApp object
CDbgPlotViewerApp theApp;
#define SHARED_SINGLE_INSTANCE_MUTEX_NAME L"|Sora|DebugPlot|single_instance_mutex"
static BOOL SetPrivilege(
HANDLE hToken, // access token handle
LPCTSTR lpszPrivilege, // name of privilege to enable/disable
BOOL bEnablePrivilege // to enable or disable privilege
)
{
TOKEN_PRIVILEGES tp;
LUID luid;
if ( !LookupPrivilegeValue(
NULL, // lookup privilege on local system
lpszPrivilege, // privilege to lookup
&luid ) ) // receives LUID of privilege
{
char msg[64];
sprintf(msg, "LookupPrivilegeValue error: %u\n", GetLastError());
OutputDebugStringA(msg);
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if (bEnablePrivilege)
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
tp.Privileges[0].Attributes = 0;
// Enable the privilege or disable all privileges.
if ( !AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES) NULL,
(PDWORD) NULL) )
{
char msg[64];
sprintf(msg, "AdjustTokenPrivileges error: %u\n", GetLastError());
OutputDebugStringA(msg);
return FALSE;
}
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{
OutputDebugStringA("The token does not have the specified privilege. \n");
return FALSE;
}
return TRUE;
}
static BOOL SetDebugPrivilege()
{
HANDLE hToken = NULL;
BOOL succ = ::OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
if (succ == TRUE)
{
BOOL succ = SetPrivilege(hToken, SE_DEBUG_NAME, TRUE);
return succ;
}
else
{
::OutputDebugStringA("OpenProcessToken failed");
return FALSE;
}
}
// CDbgPlotViewerApp initialization
BOOL CDbgPlotViewerApp::InitInstance()
{
::OutputDebugString(L"DebugPlot Viewer started\n");
SECURITY_ATTRIBUTES sa;
CreateDACLWithAllAccess(&sa);
HANDLE hMutex = CreateMutex(&sa, TRUE, SHARED_SINGLE_INSTANCE_MUTEX_NAME);
if ( GetLastError() == ERROR_ALREADY_EXISTS )
{
::CloseHandle(hMutex);
::AfxMessageBox(L"Instance already running");
_bInitialized = false;
LocalFree(sa.lpSecurityDescriptor);
return FALSE;
}
else
{
_bInitialized = true;
LocalFree(sa.lpSecurityDescriptor);
}
if (SetDebugPrivilege() == FALSE)
{
::AfxMessageBox(L"Please run DebugPlot Viewer as administrator");
_bInitialized = false;
return FALSE;
}
SetCrashDumpHandler();
ClearLog();
InitAppObj();
// InitCommonControlsEx() is required on Windows XP if an application
// manifest specifies use of ComCtl32.dll version 6 or later to enable
// visual styles. Otherwise, any window creation will fail.
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);
// Set this to include all the common control classes you want to use
// in your application.
InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);
CWinAppEx::InitInstance();
// Initialize OLE libraries
if (!AfxOleInit())
{
AfxMessageBox(IDP_OLE_INIT_FAILED);
return FALSE;
}
AfxEnableControlContainer();
EnableTaskbarInteraction(FALSE);
// AfxInitRichEdit2() is required to use RichEdit control
// AfxInitRichEdit2();
// Standard initialization
// If you are not using these features and wish to reduce the size
// of your final executable, you should remove from the following
// the specific initialization routines you do not need
// Change the registry key under which our settings are stored
// TODO: You should modify this string to be something appropriate
// such as the name of your company or organization
SetRegistryKey(_T("Sora DebugPlot Viewer v2.0"));
LoadStdProfileSettings(4); // Load standard INI file options (including MRU)
InitContextMenuManager();
InitKeyboardManager();
InitTooltipManager();
CMFCToolTipInfo ttParams;
ttParams.m_bVislManagerTheme = TRUE;
theApp.GetTooltipManager()->SetTooltipParams(AFX_TOOLTIP_TYPE_ALL,
RUNTIME_CLASS(CMFCToolTipCtrl), &ttParams);
// GDI+
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
Gdiplus::GdiplusStartup(&_gdiplusToken, &gdiplusStartupInput, NULL);
CoInitialize(NULL);
// Register the application's document templates. Document templates
// serve as the connection between documents, frame windows and views
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CDbgPlotViewerDoc),
RUNTIME_CLASS(CMainFrame), // main SDI frame window
RUNTIME_CLASS(CDbgPlotViewerView));
if (!pDocTemplate)
return FALSE;
AddDocTemplate(pDocTemplate);
// Parse command line for standard shell commands, DDE, file open
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
// Dispatch commands specified on the command line. Will return FALSE if
// app was launched with /RegServer, /Register, /Unregserver or /Unregister.
if (!ProcessShellCommand(cmdInfo))
return FALSE;
// The one and only window has been initialized, so show and update it
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
// call DragAcceptFiles only if there's a suffix
// In an SDI app, this should occur after ProcessShellCommand
return TRUE;
}
int CDbgPlotViewerApp::ExitInstance()
{
//TODO: handle additional resources you may have added
if (_bInitialized)
{
CoUninitialize();
// GDI+
Gdiplus::GdiplusShutdown(_gdiplusToken);
AfxOleTerm(FALSE);
DeiniteAppObj();
}
return CWinAppEx::ExitInstance();
}
// CDbgPlotViewerApp message handlers
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialogEx
{
public:
CAboutDlg();
// Dialog Data
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()
// App command to run the dialog
void CDbgPlotViewerApp::OnAppAbout()
{
CAboutDlg aboutDlg;
aboutDlg.DoModal();
}
// CDbgPlotViewerApp customization load/save methods
void CDbgPlotViewerApp::PreLoadState()
{
BOOL bNameValid;
CString strName;
bNameValid = strName.LoadString(IDS_EDIT_MENU);
ASSERT(bNameValid);
//GetContextMenuManager()->AddMenu(strName, IDR_POPUP_EDIT);
bNameValid = strName.LoadString(IDS_EXPLORER);
ASSERT(bNameValid);
//GetContextMenuManager()->AddMenu(strName, IDR_POPUP_EXPLORER);
GetContextMenuManager()->AddMenu(strName, IDR_POPUP_CHANNEL_EXPLORER);
GetContextMenuManager()->AddMenu(strName, IDR_POPUP_TEXT_CHANNEL);
}
void CDbgPlotViewerApp::LoadCustomState()
{
}
void CDbgPlotViewerApp::SaveCustomState()
{
}
// CDbgPlotViewerApp message handlers
bool CDbgPlotViewerApp::DeleteDirRecursive(const std::wstring& dir, bool bDir, bool bContent)
{
wstring directoryname = dir;
if(dir.at(directoryname.size()-1) != '\\') directoryname += '\\';
if (bContent)
{
WIN32_FIND_DATAW fdata;
HANDLE dhandle;
//BUG 1: Adding a extra \ to the directory name..
directoryname += L"*";
dhandle = FindFirstFileW(directoryname.c_str(), &fdata);
//BUG 2: Not checking for invalid file handle return from FindFirstFileA
if( dhandle != INVALID_HANDLE_VALUE )
{
// Loop through all the files in the main directory and delete files & make a list of directories
while(true)
{
if(FindNextFileW(dhandle, &fdata))
{
std::wstring filename = fdata.cFileName;
if(filename.compare(L"..") != 0)
{
//BUG 3: caused by BUG 1 - Removing too many characters from string.. removing 1 instead of 2
std::wstring filelocation = directoryname.substr(0, directoryname.size()-1) + filename;
// If we've encountered a directory then recall this function for that specific folder.
//BUG 4: not really a bug, but spurious function call - we know its a directory from FindData already, use it.
if( (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
DeleteFileW(filelocation.c_str());
else
DeleteDirRecursive(filelocation, true, true);
}
} else if(GetLastError() == ERROR_NO_MORE_FILES) break;
}
directoryname = directoryname.substr(0, directoryname.size()-2);
//BUG 5: Not closing the FileFind with FindClose - OS keeps handles to directory open. MAIN BUG
FindClose( dhandle );
}
}
if (bDir)
{
HANDLE DirectoryHandle;
DirectoryHandle = CreateFileW(directoryname.c_str(),
FILE_LIST_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
NULL);
//BUG 6: Not checking CreateFileA for invalid handle return.
if( DirectoryHandle != INVALID_HANDLE_VALUE )
{
bool DeletionResult = (RemoveDirectoryW(directoryname.c_str()) != 0)?true:false;
CloseHandle(DirectoryHandle);
return DeletionResult;
}
else
{
return true;
}
}
return true;
}
void CDbgPlotViewerApp::SetCrashDumpHandler()
{
if (_bEnableCrashDump)
SetCrashDump();
}
void CDbgPlotViewerApp::ClearLog()
{
DWORD requiredLen = ::GetCurrentDirectory(0, NULL);
if (requiredLen == 0)
return;
const wchar_t * dir = L"\\logs";
requiredLen += (wcslen(dir) + 1);
wchar_t * path = new wchar_t[requiredLen];
DWORD ret = ::GetCurrentDirectory(requiredLen, path);
if (ret == 0)
{
delete [] path;
return;
}
wcscat(path, dir);
DeleteDirRecursive(path, true, true);
if (path)
delete [] path;
}
void CDbgPlotViewerApp::InitAppObj()
{
_serialGen = make_shared<SoraDbgPlot::Common::SharedSerialNumGenerator>(
SharedNameManager::GetSerialNumGeneratorName()
);
_taskQueue = make_shared<TaskQueue>();
channelManager = make_shared<SharedChannelManager>();
objLookup = make_shared<ObjLookup>();
plotWindowOpenedContainer = make_shared<PlotWindowOpenedContainer>();
plotOperationDriver = make_shared<PlotOperationDriver>();
controlPanelDriver = make_shared<ControlPanelDriver>();
playPauseController = make_shared<PlotWndPlayPauseController>();
RouteMessage_SharedObj();
RouteMessage_TreeUpdate();
RouteMessage_OpenOperation();
RouteMessage_SaveLoad();
RouteMessage_PlayPause();
}
void CDbgPlotViewerApp::DeiniteAppObj()
{
objLookup->Clear();
channelManager->Clear();
plotWindowOpenedContainer->Clear();
channelManager.reset();
objLookup.reset();
plotWindowOpenedContainer.reset();
plotOperationDriver.reset();
controlPanelDriver.reset();
playPauseController.reset();
currentObject.reset();
_taskQueue.reset();
while(1)
{
int numQueue = TaskQueue::WaitAndClean(1000);
#ifdef _DEBUG
//int numHandler = SoraDbgPlot::Event::EventHandlerCount();
//TRACE0("Waiting for task queue tasks\n");
//TRACE1("Task queue count: %d\n", numQueue);
//TRACE1("Event handler unreleased: %d\n", numHandler);
//TRACE1("Task num in queue: %d\n", SoraDbgPlot::Task::TaskQueue::MonitorTaskInQueue());
//TRACE1("Task num to run: %d\n", SoraDbgPlot::Task::TaskQueue::MonitorTaskCntToRun());
//TRACE1("Task num runnning: %d\n", SoraDbgPlot::Task::TaskQueue::MonitorTaskCntRunning());
//TRACE1("Task queue op num: %d\n", SoraDbgPlot::Task::TaskQueue::MonitorTaskQueueOpCnt());
#endif
if (numQueue == 0)
break;
}
_serialGen.reset();
ClearLog();
::OutputDebugString(L"DebugPlot Viewer exited\n");
}
void CDbgPlotViewerApp::RouteMessage_SaveLoad()
{
auto lu = objLookup;
auto pl = plotWindowOpenedContainer;
auto pod = theApp.plotOperationDriver;
auto playPauseController = theApp.playPauseController;
lu->EventPlotWindowLoaded.Subscribe([pod](const void * sender, const ObjLookup::PlotWindowLoadedEvent & e){
pod->AddPlotWnd(e._plotWnd);
});
lu->EventPlotWindowLoaded.Subscribe([playPauseController](const void * sender, const ObjLookup::PlotWindowLoadedEvent & e){
playPauseController->AddProcessPlotWnd(e._process, e._plotWnd);
});
lu->EventPlotWindowLoaded.Subscribe([pl](const void * sender, const ObjLookup::PlotWindowLoadedEvent & e){
pl->AddPlotWindow(e._plotWnd, e._rect);
});
lu->EventChannelLoaded.Subscribe([pl](const void * sender, const ObjLookup::ChannelLoadedEvent & e){
pl->AddChannel(e._plotWnd, e._channel, e._rect);
});
}
void CDbgPlotViewerApp::RouteMessage_OpenOperation()
{
auto lu = objLookup;
auto cm = channelManager;
auto pl = plotWindowOpenedContainer;
auto pod = theApp.plotOperationDriver;
auto playPauseController = theApp.playPauseController;
pl->EventCloseChannel.Subscribe([lu](const void * sender, const PlotWindowOpenedContainer::CloseChannelEvent & e){
lu->CloseChannel(e._channel);
});
pl->EventAddPlotWndRequest.Subscribe([lu, pl](const void * sender, const PlotWindowOpenedContainer::AddPlotWndParam & e){
auto succ = make_shared<bool>();
auto process = e._process;
auto channel = e._channel;
auto point = e._point;
auto pl2 = pl;
lu->OpenChannel(channel, [pl2, process, channel, point](bool succ){
if (succ)
pl2->AddPlotWindow(process, channel, point);
});
});
pl->EventAddChannelRequest.Subscribe([lu, pl](const void * sender, const PlotWindowOpenedContainer::AddChannelRequestEvent & e){
auto succ = make_shared<bool>();
auto channel = e._channel;
auto plotWnd = e._plotWnd;
auto rect = e._rect;
lu->CloseChannel(channel);
auto pl2 = pl;
lu->OpenChannel(channel, [pl2, plotWnd, channel, rect](bool succ){
pl2->AddChannel(plotWnd, channel, rect);
});
});
pl->EventClosePlotWnd.Subscribe([pod](const void * sender, const PlotWindowOpenedContainer::ClosePlotWndEvent & e){
pod->RemovePlotWnd(e._plotWnd);
});
pl->EventClosePlotWnd.Subscribe([lu](const void * sender, const PlotWindowOpenedContainer::ClosePlotWndEvent & e){
lu->RemovePlotWnd(e._plotWnd);
});
pl->EventClosePlotWnd.Subscribe([playPauseController](const void * sender, const PlotWindowOpenedContainer::ClosePlotWndEvent & e){
playPauseController->RemovePlotWnd(e._plotWnd);
});
pl->EventPlotWndAdded.Subscribe([pod](const void * sender, const PlotWindowOpenedContainer::PlotWndAddedParam & e){
pod->AddPlotWnd(e._plotWnd);
});
pl->EventPlotWndAdded.Subscribe([playPauseController](const void * sender, const PlotWindowOpenedContainer::PlotWndAddedParam & e){
playPauseController->AddProcessPlotWnd(e._process, e._plotWnd);
});
pl->EventPlotWndAdded.Subscribe([lu](const void * sender, const PlotWindowOpenedContainer::PlotWndAddedParam & e){
lu->AddPlotWnd(e._plotWnd, e._process);
});
}
void CDbgPlotViewerApp::RouteMessage_TreeUpdate()
{
//auto lu = objLookup;
//lu->EventProcessChannelTreeChanged.Subscribe([](const void * sender, const ObjLookup::ProcessChannelTree & tree){
// TRACE0("Ps-Ch tree changed\n");
// for (auto iterPsChMap = tree.begin(); iterPsChMap != tree.end(); ++iterPsChMap)
// {
// auto process = iterPsChMap->first;
// TRACE2("process [%d] [%s]\n", process->Pid(), process->Name().c_str());
// auto channelMap = iterPsChMap->second;
// for (auto iterChannel = channelMap.begin(); iterChannel != channelMap.end(); ++iterChannel)
// {
// TRACE2("channel [%d] [%s]\n", (*iterChannel)->Pid(), (*iterChannel)->Name().c_str());
// }
// }
//});
}
void CDbgPlotViewerApp::RouteMessage_SharedObj()
{
auto lu = objLookup;
auto cm = channelManager;
auto pl = plotWindowOpenedContainer;
cm->EventDiscoverdProcess.Subscribe([lu](const void * sender, const vector<shared_ptr<SharedProcess> > & vec){
TRACE0("New shared process discoved\n");
lu->AddSharedProcess(vec);
});
cm->EventProcessClosed.Subscribe([lu](const void * sender, const vector<shared_ptr<SharedProcess> > & vec){
TRACE0("Shared Process closed\n");
lu->RemoveSharedProcess(vec);
});
cm->EventDiscoverdChannel.Subscribe([lu](const void * sender, const vector<shared_ptr<SharedChannel> > & vec){
TRACE0("New shared channel discovered\n");
lu->AddSharedChannel(vec);
});
cm->EventChannelClosed.Subscribe([lu](const void * sender, const vector<shared_ptr<SharedChannel> > & vec){
TRACE0("Shared channel closed\n");
lu->RemoveSharedChannel(vec);
});
// control panel related
auto controlPanelDriver = theApp.controlPanelDriver;
lu->EventProcessOpenedAttatched.Subscribe([controlPanelDriver](const void * sender, const std::shared_ptr<ProcessOpened> & process){
controlPanelDriver->AddProcessOpened(process);
});
lu->EventProcessOpenedDeattatched.Subscribe([controlPanelDriver](const void * sender, const std::shared_ptr<ProcessOpened> & process){
controlPanelDriver->RemoveProcess(process);
});
lu->EventProcessOpenedAttatched.Subscribe([pl](const void * sender, const std::shared_ptr<ProcessOpened> & process){
pl->PrcessAttatchDetatch(process, true);
});
lu->EventProcessOpenedDeattatched.Subscribe([pl](const void * sender, const std::shared_ptr<ProcessOpened> & process){
pl->PrcessAttatchDetatch(process, false);
});
}
void CDbgPlotViewerApp::RouteMessage_PlayPause()
{
auto theObjLookup = this->objLookup;
auto thePlayPauseController = this->playPauseController;
theObjLookup->EventPauseProcess.Subscribe([thePlayPauseController](const void * sender, const std::shared_ptr<ProcessOpened> & process){
thePlayPauseController->PauseProcess(process);
});
}

Просмотреть файл

@ -0,0 +1,79 @@
// DbgPlotViewer.h : main header file for the DbgPlotViewer application
//
#pragma once
#ifndef __AFXWIN_H__
#error "include 'stdafx.h' before including this file for PCH"
#endif
#include "resource.h" // main symbols
#include <memory>
#include "SharedSerialNumGenerator.h"
#include "SharedChannelManager.h"
#include "GlobalObjLookup.h"
#include "PlotWindowOpenedContainer.h"
#include "PlotOperationDriver.h"
#include "ControlPanelDriver.h"
#include "PlotWndPlayPauseController.h"
// CDbgPlotViewerApp:
// See DbgPlotViewer.cpp for the implementation of this class
//
class CDbgPlotViewerApp : public CWinAppEx
{
public:
CDbgPlotViewerApp();
// Overrides
public:
virtual BOOL InitInstance();
virtual int ExitInstance();
// Implementation
BOOL m_bHiColorIcons;
virtual void PreLoadState();
virtual void LoadCustomState();
virtual void SaveCustomState();
afx_msg void OnAppAbout();
DECLARE_MESSAGE_MAP()
public:
std::shared_ptr<SoraDbgPlot::SharedObj::SharedChannelManager> channelManager;
std::shared_ptr<ObjLookup> objLookup;
std::shared_ptr<PlotWindowOpenedContainer> plotWindowOpenedContainer;
std::shared_ptr<PlotOperationDriver> plotOperationDriver;
std::shared_ptr<PropObject> currentObject;
std::shared_ptr<ControlPanelDriver> controlPanelDriver;
std::shared_ptr<PlotWndPlayPauseController> playPauseController;
private:
bool DeleteDirRecursive(const std::wstring &path, bool bDir, bool bContent);
void ClearLog();
void SetCrashDumpHandler();
void InitAppObj();
void DeiniteAppObj();
void RouteMessage_SharedObj();
void RouteMessage_TreeUpdate();
void RouteMessage_OpenOperation();
void RouteMessage_SaveLoad();
void RouteMessage_PlayPause();
bool _bEnableCrashDump;
std::shared_ptr<SoraDbgPlot::Common::SharedSerialNumGenerator> _serialGen;
std::shared_ptr<SoraDbgPlot::Task::TaskQueue> _taskQueue;
bool _bInitialized;
private:
ULONG_PTR _gdiplusToken; // GDI+
};
extern CDbgPlotViewerApp theApp;

Двоичные данные
DebugTool/source/DbgPlotViewer/DbgPlotViewer.rc Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,302 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{19D199A8-1BF1-49E4-97F6-B4CB51F6F58B}</ProjectGuid>
<SccProjectName>
</SccProjectName>
<SccAuxPath>
</SccAuxPath>
<SccLocalPath>
</SccLocalPath>
<SccProvider>
</SccProvider>
<RootNamespace>DbgPlotViewer</RootNamespace>
<Keyword>MFCProj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<UseOfMfc>Dynamic</UseOfMfc>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<UseOfMfc>Dynamic</UseOfMfc>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>C:\Program Files %28x86%29\Visual Leak Detector\include;$(IncludePath)</IncludePath>
<LibraryPath>C:\Program Files %28x86%29\Visual Leak Detector\lib\Win32;$(LibraryPath)</LibraryPath>
<TargetName>DbgPlot</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<TargetName>DbgPlot</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;USER_MODE;DEBUG_INTERNAL_DATAFILTER;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\DebugPlotU;..\..\..\kernel\core\inc;..\Common;..\LibViewer</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType>
<CallingConvention>StdCall</CallingConvention>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>msxml6.lib;usora.lib;LibViewer.lib;Psapi.lib;Common.lib;DebugPlotU_Viewer.lib;DbgHelp.lib</AdditionalDependencies>
<AdditionalLibraryDirectories>..\Debug;..\..\..\target\ke\chk_wxp_x86\i386</AdditionalLibraryDirectories>
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
</Link>
<Midl>
<MkTypLibCompatible>false</MkTypLibCompatible>
<ValidateAllParameters>true</ValidateAllParameters>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</Midl>
<ResourceCompile>
<Culture>0x0409</Culture>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(IntDir);..\..\..\build;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;USER_MODE;ENABLE_CRASH_DUMP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\DebugPlotU;..\..\..\kernel\core\inc;..\Common;..\LibViewer</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType>
<CallingConvention>StdCall</CallingConvention>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>msxml6.lib;usora.lib;DebugPlotU_Viewer.lib;LibViewer.lib;Psapi.lib;DbgHelp.lib</AdditionalDependencies>
<AdditionalLibraryDirectories>..\Release;..\..\..\target\ke\fre_wxp_x86\i386</AdditionalLibraryDirectories>
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
</Link>
<Midl>
<MkTypLibCompatible>false</MkTypLibCompatible>
<ValidateAllParameters>true</ValidateAllParameters>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</Midl>
<ResourceCompile>
<Culture>0x0409</Culture>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(IntDir);..\..\..\build;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemGroup>
<None Include="ClassDiagram.cd" />
<None Include="ClassDiagram1.cd" />
<None Include="ReadMe.txt" />
<None Include="res\autolayout.ico" />
<None Include="res\bitmap1.bmp" />
<None Include="res\bmp00001.bmp" />
<None Include="res\channelExplorer.ico" />
<None Include="res\channel_bmp.bmp" />
<None Include="res\controlPanel.ico" />
<None Include="res\DbgPlotViewer.ico" />
<None Include="res\DbgPlotViewer.rc2" />
<None Include="res\DbgPlotViewerDoc.ico" />
<None Include="res\menuimages.bmp" />
<None Include="res\menuimages_hc.bmp" />
<None Include="res\pause32.bmp" />
<None Include="res\properties.ico" />
<None Include="res\run32.bmp" />
<None Include="res\singlestep32.bmp" />
<None Include="res\Toolbar.bmp" />
<None Include="res\toolbar1.bmp" />
<None Include="res\Toolbar256.bmp" />
<None Include="UserImages.bmp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="AsyncObject.h" />
<ClInclude Include="AutoLayoutSlider.h" />
<ClInclude Include="BaseProperty.h" />
<ClInclude Include="BitmapPlotWnd.h" />
<ClInclude Include="ChannelAddable.h" />
<ClInclude Include=".\ChannelProperty.h" />
<ClInclude Include="ChannelOpened.h" />
<ClInclude Include="ChannelOpenedDots.h" />
<ClInclude Include="ChannelOpenedFixedLengthType.h" />
<ClInclude Include="ChannelOpenedLine.h" />
<ClInclude Include="ChannelOpenedLineType.h" />
<ClInclude Include="ChannelOpenedLog.h" />
<ClInclude Include="ChannelOpenedSpectrum.h" />
<ClInclude Include="ChannelOpenedText.h" />
<ClInclude Include="ChannelOpenedTextType.h" />
<ClInclude Include="ChannelTreeCtrl.h" />
<ClInclude Include=".\ViewerAppConst.h" />
<ClInclude Include="ControlPanelDriver.h" />
<ClInclude Include="ControlPanelList.h" />
<ClInclude Include="ControlPanelWnd.h" />
<ClInclude Include="CrashDump.h" />
<ClInclude Include="CustomButton.h" />
<ClInclude Include="DbgPlotViewer.h" />
<ClInclude Include="DbgPlotViewerDoc.h" />
<ClInclude Include="DbgPlotViewerView.h" />
<ClInclude Include="DockableWndContainer.h" />
<ClInclude Include="GlobalObjLookup.h" />
<ClInclude Include=".\Targetable.h" />
<ClInclude Include="GridAlg.h" />
<ClInclude Include="HelperFunc.h" />
<ClInclude Include="Invokable.h" />
<ClInclude Include="BitmapTypeSettings.h" />
<ClInclude Include="MainFrm.h" />
<ClInclude Include=".\PropObject.h" />
<ClInclude Include="PassiveTaskQueue.h" />
<ClInclude Include="PlayControlWnd.h" />
<ClInclude Include=".\PlotWindowOpenedContainer.h" />
<ClInclude Include="PlotOperationDriver.h" />
<ClInclude Include=".\PlotWindowLineTypeProperty.h" />
<ClInclude Include="PlotWindowDotsProperty.h" />
<ClInclude Include="PlotWindowOpened.h" />
<ClInclude Include="PlotWindowOpenedBitmapType.h" />
<ClInclude Include="PlotWindowOpenedDots.h" />
<ClInclude Include="PlotWindowOpenedLine.h" />
<ClInclude Include="PlotWindowOpenedLineType.h" />
<ClInclude Include="PlotWindowOpenedLog.h" />
<ClInclude Include="PlotWindowOpenedSpectrum.h" />
<ClInclude Include="PlotWindowOpenedText.h" />
<ClInclude Include="PlotWindowOpenedTextType.h" />
<ClInclude Include="PlotWindowTextTypeProperty.h" />
<ClInclude Include="PlotWnd.h" />
<ClInclude Include="PlotWndContainer.h" />
<ClInclude Include="PlotWndPlayPauseController.h" />
<ClInclude Include="ProcessOpened.h" />
<ClInclude Include="ReplayBufferTrackBar.h" />
<ClInclude Include="Resource.h" />
<ClInclude Include="Serializable.h" />
<ClInclude Include="SettingsPlotWindow.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="SubBitmapPlotWnd.h" />
<ClInclude Include="SubPlotWnd.h" />
<ClInclude Include="SubTextTypePlotWnd.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="TemplateProperty.h" />
<ClInclude Include="TextPlayControlWnd.h" />
<ClInclude Include="TextTypePlotWnd.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="AsyncObject.cpp" />
<ClCompile Include="AutoLayoutSlider.cpp" />
<ClCompile Include="BaseProperty.cpp" />
<ClCompile Include="BitmapPlotWnd.cpp" />
<ClCompile Include=".\ChannelProperty.cpp" />
<ClCompile Include="ChannelAddable.cpp" />
<ClCompile Include="ChannelOpened.cpp" />
<ClCompile Include="ChannelOpenedDots.cpp" />
<ClCompile Include="ChannelOpenedFixedLengthType.cpp" />
<ClCompile Include="ChannelOpenedLine.cpp" />
<ClCompile Include="ChannelOpenedLineType.cpp" />
<ClCompile Include="ChannelOpenedLog.cpp" />
<ClCompile Include="ChannelOpenedSpectrum.cpp" />
<ClCompile Include="ChannelOpenedText.cpp" />
<ClCompile Include="ChannelOpenedTextType.cpp" />
<ClCompile Include="ChannelTreeCtrl.cpp" />
<ClCompile Include=".\ViewerAppConst.cpp" />
<ClCompile Include="ControlPanelDriver.cpp" />
<ClCompile Include="ControlPanelList.cpp" />
<ClCompile Include="ControlPanelWnd.cpp" />
<ClCompile Include="CrashDump.cpp" />
<ClCompile Include="CustomButton.cpp" />
<ClCompile Include="DbgPlotViewer.cpp" />
<ClCompile Include="DbgPlotViewerDoc.cpp" />
<ClCompile Include="DbgPlotViewerView.cpp" />
<ClCompile Include="DockableWndContainer.cpp" />
<ClCompile Include="GlobalObjLookup.cpp" />
<ClCompile Include="GridAlg.cpp" />
<ClCompile Include="HelperFunc.cpp" />
<ClCompile Include="Invokable.cpp" />
<ClCompile Include="BitmapTypeSettings.cpp" />
<ClCompile Include="MainFrm.cpp" />
<ClCompile Include=".\PropObject.cpp" />
<ClCompile Include="PlayControlWnd.cpp" />
<ClCompile Include=".\PlotWindowOpenedContainer.cpp" />
<ClCompile Include="PlotOperationDriver.cpp" />
<ClCompile Include=".\PlotWindowLineTypeProperty.cpp" />
<ClCompile Include="PlotWindowDotsProperty.cpp" />
<ClCompile Include="PlotWindowOpened.cpp" />
<ClCompile Include="PlotWindowOpenedBitmapType.cpp" />
<ClCompile Include="PlotWindowOpenedDots.cpp" />
<ClCompile Include="PlotWindowOpenedLine.cpp" />
<ClCompile Include="PlotWindowOpenedLineType.cpp" />
<ClCompile Include="PlotWindowOpenedLog.cpp" />
<ClCompile Include="PlotWindowOpenedSpectrum.cpp" />
<ClCompile Include="PlotWindowOpenedText.cpp" />
<ClCompile Include="PlotWindowOpenedTextType.cpp" />
<ClCompile Include="PlotWindowTextTypeProperty.cpp" />
<ClCompile Include="PlotWnd.cpp" />
<ClCompile Include="PlotWndContainer.cpp" />
<ClCompile Include="PlotWndPlayPauseController.cpp" />
<ClCompile Include="ProcessOpened.cpp" />
<ClCompile Include="ReplayBufferTrackBar.cpp" />
<ClCompile Include="SettingsPlotWindow.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="SubBitmapPlotWnd.cpp" />
<ClCompile Include="SubPlotWnd.cpp" />
<ClCompile Include="SubTextTypePlotWnd.cpp" />
<ClCompile Include="TemplateProperty.cpp" />
<ClCompile Include="TextPlayControlWnd.cpp" />
<ClCompile Include="TextTypePlotWnd.cpp" />
<ClCompile Include="Vld.cpp" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="DbgPlotViewer.rc" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Common\Common.vcxproj">
<Project>{54730ad7-5b11-493b-adcc-8e4ec3c0204a}</Project>
</ProjectReference>
<ProjectReference Include="..\LibViewer\LibViewer.vcxproj">
<Project>{6ae0ea97-eb5a-40e1-92d8-54532e208be1}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
<ProjectExtensions>
<VisualStudio>
<UserProperties RESOURCE_FILE="DbgPlotViewer.rc" />
</VisualStudio>
</ProjectExtensions>
</Project>

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше