Commit 8ca7061b authored by captainwong's avatar captainwong

registry

parent ba14ba35
......@@ -7,3 +7,7 @@
#else
#error "jlib only support linux and windows"
#endif
#ifdef JLIB_WINDOWS
#define _CRT_SECURE_NO_WARNINGS
#endif
#pragma once
#include "config.h"
#include "logstream.h"
#include "timestamp.h"
#include "currentthread.h"
#include <stdlib.h> // getenv
namespace jlib
{
......@@ -11,59 +14,169 @@ class TimeZone;
class Logger
{
public:
enum class LogLevel {
LOGLEVEL_TRACE,
LOGLEVEL_DEBUG,
LOGLEVEL_INFO,
LOGLEVEL_WARN,
LOGLEVEL_ERROR,
LOGLEVEL_FATAL,
LOGLEVEL_COUNT,
};
// compile time calculation of basename of source file
struct SourceFile
{
template <int N>
SourceFile(const char (&arr)[N]) : data_(arr) , size_(N - 1) {
const char* slash = strrchr(data_, '/');
if (slash) { data_ = slash + 1; }
size_ -= static_cast<int>(data_ - arr);
}
explicit SourceFile(const char* filename) : data_(filename) {
const char* slash = strrchr(filename, '/');
if (slash) { data_ = slash + 1; }
size_ = static_cast<int>(strlen(data_));
}
const char* data_;
int size_;
};
Logger(SourceFile file, int line);
enum LogLevel {
LOGLEVEL_TRACE,
LOGLEVEL_DEBUG,
LOGLEVEL_INFO,
LOGLEVEL_WARN,
LOGLEVEL_ERROR,
LOGLEVEL_FATAL,
LOGLEVEL_COUNT,
};
// compile time calculation of basename of source file
struct SourceFile
{
template <int N>
SourceFile(const char(&arr)[N]) : data_(arr), size_(N - 1) {
const char* slash = strrchr(data_, '/');
if (slash) { data_ = slash + 1; }
size_ -= static_cast<int>(data_ - arr);
}
explicit SourceFile(const char* filename) : data_(filename) {
const char* slash = strrchr(filename, '/');
if (slash) { data_ = slash + 1; }
size_ = static_cast<int>(strlen(data_));
}
const char* data_;
int size_;
};
Logger(SourceFile file, int line);
Logger(SourceFile file, int line, LogLevel level);
Logger(SourceFile file, int line, LogLevel level, const char *func);
Logger(SourceFile file, int line, LogLevel level, const char* func);
Logger(SourceFile file, int line, bool toAbort);
~Logger();
LogStream &stream() { return impl_.stream_; }
LogStream& stream() { return impl_.stream_; }
static LogLevel logLevel();
static LogLevel logLevel() { return logLevel_; }
static void setLogLevel(LogLevel level);
typedef void (*OutputFunc)(const char *msg, int len);
typedef void (*OutputFunc)(const char* msg, int len);
typedef void (*FlushFunc)();
static void setOutput(OutputFunc);
static void setFlush(FlushFunc);
static void setTimeZone(const TimeZone &tz);
static void setTimeZone(const TimeZone& tz);
private:
class Impl
{
public:
};
class Impl
{
public:
typedef Logger::LogLevel LogLevel;
Impl(LogLevel level, int old_errno, const SourceFile& file, int line);
void formatTime();
void finish();
Timestamp time_;
LogStream stream_;
LogLevel level_;
int line_;
SourceFile basename_;
};
static LogLevel logLevel_;
Impl impl_;
};
static void defaultOutput(const char* msg, int len) { fwrite(msg, 1, len, stdout); }
static void defaultFlush() { fflush(stdout); }
static Logger::OutputFunc g_output = defaultOutput;
static Logger::FlushFunc g_flush = defaultFlush;
namespace detail
{
static const char* LogLevelName[Logger::LogLevel::LOGLEVEL_COUNT] =
{
"TRACE ",
"DEBUG ",
"INFO ",
"WARN ",
"ERROR ",
"FATAL ",
};
static Logger::LogLevel initLogLevel() {
if (::getenv("JLIB_LOGLEVEL_TRACE")) {
return Logger::LogLevel::LOGLEVEL_TRACE;
} else if (::getenv("JLIB_LOGLEVEL_DEBUG")) {
return Logger::LogLevel::LOGLEVEL_DEBUG;
} else {
return Logger::LogLevel::LOGLEVEL_INFO;
}
}
struct T
{
explicit T(const char* str, unsigned int len)
: str_(str)
, len_(len)
{
assert(strlen(str) == len);
}
const char* str_;
const unsigned int len_;
};
thread_local char t_errnobuf[512] = { 0 };
thread_local char t_time[64] = { 0 };
thread_local time_t t_lastSecond = 0;
} // detail
Logger::LogLevel Logger::logLevel_ = detail::initLogLevel();
inline LogStream& operator<<(LogStream& s, const Logger::SourceFile& f) {
s.append(f.data_, f.size_); return s;
}
inline LogStream& operator<<(LogStream& s, detail::T t) {
s.append(t.str_, t.len_); return s;
}
static const char* strerror_t(int savedErrno) {
strerror_s(detail::t_errnobuf, savedErrno);
return detail::t_errnobuf;
}
Logger::Impl::Impl(LogLevel level, int old_errno, const SourceFile& file, int line)
: time_(Timestamp::now())
, stream_()
, level_(level)
, line_(line)
, basename_(file)
{
formatTime();
CurrentThread::tid();
stream_ << detail::T(CurrentThread::tidString(), CurrentThread::tidStringLength());
stream_ << detail::T(detail::LogLevelName[level], 6);
if (old_errno != 0) {
stream_ << strerror_t(old_errno) << " (errorno=" << old_errno << ") ";
}
}
void Logger::Impl::formatTime()
{
int64_t microSecsSinceEpoch = time_.microSecondsSinceEpoch();
time_t seconds = static_cast<time_t>(microSecsSinceEpoch / Timestamp::MICRO_SECONDS_PER_SECOND);
int microsecs = static_cast<int>(microSecsSinceEpoch % Timestamp::MICRO_SECONDS_PER_SECOND);
if (seconds != detail::t_lastSecond) {
detail::t_lastSecond = seconds;
}
}
} // namespace jlib
#pragma once
#include "config.h"
#include "copyable.h"
#include <time.h>
#include <memory>
#include <vector>
#include <string>
namespace jlib
{
namespace detail
{
struct Transition
{
time_t gmtime_;
time_t localtime_;
int localTimeIdx_;
Transition(time_t gmt, time_t localt, int localIdx)
: gmtime_(gmt)
, localtime_(localt)
, localTimeIdx_(localIdx)
{}
};
struct Compare
{
bool compareGmt_ = true;
Compare(bool gmt)
: compareGmt_(gmt)
{}
bool operator()(const Transition& lhs, const Transition& rhs) const {
if (compareGmt_) {
return lhs.gmtime_ < rhs.gmtime_;
} else {
return lhs.localtime_ < rhs.localtime_;
}
}
bool equal(const Transition& lhs, const Transition& rhs) const {
if (compareGmt_) {
return lhs.gmtime_ == rhs.gmtime_;
} else {
return lhs.localtime_ == rhs.localtime_;
}
}
};
struct LocalTime
{
time_t gmtOffset;
bool isDst;
int abbrIdx;
LocalTime(time_t offset, bool dst, int abbr)
: gmtOffset(offset)
, isDst(dst)
, abbrIdx(abbr)
{}
};
} // namespace detail
static constexpr int SECONDS_PER_DAY = 24 * 60 * 60;
class Timezone : public copyable
{
public:
explicit Timezone(const char* zonename);
Timezone(int bias, const char* tzname);
Timezone() = default; // invalid timezone
bool valid() const{
return static_cast<bool>(data_);
}
struct tm toLocalTime(time_t secondsSinceEpoch) const {
}
time_t fromLocalTime(const struct tm& tm_time) const {
}
static struct tm toUtcTime(time_t secondsSinceEpoch, bool yday = false);
static time_t fromUtcTime(const struct tm& tm_time);
/**
* @param year [1900, 2500]
* @param month [1, 12]
* @param day [1, 31]
* @param hour [0, 23]
* @param minute [0, 59]
* @param seconds [0, 59]
*/
static time_t fromUtcTime(int year, int month, int day,
int hour, int minute, int seconds) {
}
struct Data {
std::vector<detail::Transition> transitions;
std::vector<detail::LocalTime> localtimes;
std::vector<std::string> names;
std::string abbreviation;
};
private:
std::shared_ptr<Data> data_ = {};
};
} // namespace jlib
This diff is collapsed.
......@@ -48,10 +48,44 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "base", "base", "{608A105E-4
..\jlib\base\singleton.h = ..\jlib\base\singleton.h
..\jlib\base\stringpiece.h = ..\jlib\base\stringpiece.h
..\jlib\base\timestamp.h = ..\jlib\base\timestamp.h
..\jlib\base\timezone.h = ..\jlib\base\timezone.h
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_singleton", "test_singleton\test_singleton.vcxproj", "{B4B8F20B-1B3E-42CD-8B37-A734EF3CA279}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_logging", "test_logging\test_logging.vcxproj", "{3E322E9F-E560-4300-AFF8-1DCE44E7DDA2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_timezone", "test_timezone\test_timezone.vcxproj", "{8A9333D5-2981-4E92-87BF-AFFC5F99B1A4}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "win32", "win32", "{B5D9E71E-2BFE-4D04-A66A-4CB0A103CD77}"
ProjectSection(SolutionItems) = preProject
..\jlib\win32\clipboard.h = ..\jlib\win32\clipboard.h
..\jlib\win32\DeviceUniqueIdentifier.cpp = ..\jlib\win32\DeviceUniqueIdentifier.cpp
..\jlib\win32\DeviceUniqueIdentifier.h = ..\jlib\win32\DeviceUniqueIdentifier.h
..\jlib\win32\deviceuniqueidentifierheaderonly.h = ..\jlib\win32\deviceuniqueidentifierheaderonly.h
..\jlib\win32\file_op = ..\jlib\win32\file_op
..\jlib\win32\file_op.h = ..\jlib\win32\file_op.h
..\jlib\win32\memory_micros.h = ..\jlib\win32\memory_micros.h
..\jlib\win32\MtVerify.h = ..\jlib\win32\MtVerify.h
..\jlib\win32\MtVerify.h.bak = ..\jlib\win32\MtVerify.h.bak
..\jlib\win32\MyWSAError.h = ..\jlib\win32\MyWSAError.h
..\jlib\win32\odbccp32.lib = ..\jlib\win32\odbccp32.lib
..\jlib\win32\path_op.h = ..\jlib\win32\path_op.h
..\jlib\win32\registry.h = ..\jlib\win32\registry.h
..\jlib\win32\UnicodeTool.h = ..\jlib\win32\UnicodeTool.h
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "mfc", "mfc", "{9A3F45EB-C57C-4789-8177-0DEFCC5AFD0E}"
ProjectSection(SolutionItems) = preProject
..\jlib\win32\mfc\FileOper.h = ..\jlib\win32\mfc\FileOper.h
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{21DC893D-AB0B-48E1-9E23-069A025218D9}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "win32_tests", "win32_tests", "{0E6598D3-602D-4552-97F7-DC5AB458D553}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_registry", "test_registry\test_registry.vcxproj", "{519E5179-6E95-44EF-A63B-65C9C9C47A3B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
......@@ -122,13 +156,51 @@ Global
{B4B8F20B-1B3E-42CD-8B37-A734EF3CA279}.Release|x64.Build.0 = Release|x64
{B4B8F20B-1B3E-42CD-8B37-A734EF3CA279}.Release|x86.ActiveCfg = Release|Win32
{B4B8F20B-1B3E-42CD-8B37-A734EF3CA279}.Release|x86.Build.0 = Release|Win32
{3E322E9F-E560-4300-AFF8-1DCE44E7DDA2}.Debug|x64.ActiveCfg = Debug|x64
{3E322E9F-E560-4300-AFF8-1DCE44E7DDA2}.Debug|x64.Build.0 = Debug|x64
{3E322E9F-E560-4300-AFF8-1DCE44E7DDA2}.Debug|x86.ActiveCfg = Debug|Win32
{3E322E9F-E560-4300-AFF8-1DCE44E7DDA2}.Debug|x86.Build.0 = Debug|Win32
{3E322E9F-E560-4300-AFF8-1DCE44E7DDA2}.Release|x64.ActiveCfg = Release|x64
{3E322E9F-E560-4300-AFF8-1DCE44E7DDA2}.Release|x64.Build.0 = Release|x64
{3E322E9F-E560-4300-AFF8-1DCE44E7DDA2}.Release|x86.ActiveCfg = Release|Win32
{3E322E9F-E560-4300-AFF8-1DCE44E7DDA2}.Release|x86.Build.0 = Release|Win32
{8A9333D5-2981-4E92-87BF-AFFC5F99B1A4}.Debug|x64.ActiveCfg = Debug|x64
{8A9333D5-2981-4E92-87BF-AFFC5F99B1A4}.Debug|x64.Build.0 = Debug|x64
{8A9333D5-2981-4E92-87BF-AFFC5F99B1A4}.Debug|x86.ActiveCfg = Debug|Win32
{8A9333D5-2981-4E92-87BF-AFFC5F99B1A4}.Debug|x86.Build.0 = Debug|Win32
{8A9333D5-2981-4E92-87BF-AFFC5F99B1A4}.Release|x64.ActiveCfg = Release|x64
{8A9333D5-2981-4E92-87BF-AFFC5F99B1A4}.Release|x64.Build.0 = Release|x64
{8A9333D5-2981-4E92-87BF-AFFC5F99B1A4}.Release|x86.ActiveCfg = Release|Win32
{8A9333D5-2981-4E92-87BF-AFFC5F99B1A4}.Release|x86.Build.0 = Release|Win32
{519E5179-6E95-44EF-A63B-65C9C9C47A3B}.Debug|x64.ActiveCfg = Debug|x64
{519E5179-6E95-44EF-A63B-65C9C9C47A3B}.Debug|x64.Build.0 = Debug|x64
{519E5179-6E95-44EF-A63B-65C9C9C47A3B}.Debug|x86.ActiveCfg = Debug|Win32
{519E5179-6E95-44EF-A63B-65C9C9C47A3B}.Debug|x86.Build.0 = Debug|Win32
{519E5179-6E95-44EF-A63B-65C9C9C47A3B}.Release|x64.ActiveCfg = Release|x64
{519E5179-6E95-44EF-A63B-65C9C9C47A3B}.Release|x64.Build.0 = Release|x64
{519E5179-6E95-44EF-A63B-65C9C9C47A3B}.Release|x86.ActiveCfg = Release|Win32
{519E5179-6E95-44EF-A63B-65C9C9C47A3B}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{155F525A-FA2F-471F-A2DF-9B77E7CCCFA5} = {21DC893D-AB0B-48E1-9E23-069A025218D9}
{1E6D1113-2EDE-4E7E-BF17-A3663101C3AE} = {0E6598D3-602D-4552-97F7-DC5AB458D553}
{CA7812A3-9E48-4A94-B39A-32EED587E38A} = {0E6598D3-602D-4552-97F7-DC5AB458D553}
{A4B1CDB2-7325-4E22-AD0A-1D2907924CDB} = {0E6598D3-602D-4552-97F7-DC5AB458D553}
{B12702AD-ABFB-343A-A199-8E24837244A3} = {21DC893D-AB0B-48E1-9E23-069A025218D9}
{8A39D7AF-50AF-43BD-8CC6-DA20B6349F03} = {21DC893D-AB0B-48E1-9E23-069A025218D9}
{372670F2-83A5-4058-B93C-BB0DCC1521ED} = {21DC893D-AB0B-48E1-9E23-069A025218D9}
{5A2CA1BE-5A4B-41B0-B74A-F86AB433F4A5} = {42703978-A988-403D-9723-E35527FA8A07}
{608A105E-40DB-44FD-8FC2-A66AB921688D} = {42703978-A988-403D-9723-E35527FA8A07}
{B4B8F20B-1B3E-42CD-8B37-A734EF3CA279} = {21DC893D-AB0B-48E1-9E23-069A025218D9}
{3E322E9F-E560-4300-AFF8-1DCE44E7DDA2} = {21DC893D-AB0B-48E1-9E23-069A025218D9}
{8A9333D5-2981-4E92-87BF-AFFC5F99B1A4} = {21DC893D-AB0B-48E1-9E23-069A025218D9}
{B5D9E71E-2BFE-4D04-A66A-4CB0A103CD77} = {42703978-A988-403D-9723-E35527FA8A07}
{9A3F45EB-C57C-4789-8177-0DEFCC5AFD0E} = {B5D9E71E-2BFE-4D04-A66A-4CB0A103CD77}
{0E6598D3-602D-4552-97F7-DC5AB458D553} = {21DC893D-AB0B-48E1-9E23-069A025218D9}
{519E5179-6E95-44EF-A63B-65C9C9C47A3B} = {0E6598D3-602D-4552-97F7-DC5AB458D553}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A8EBEA58-739C-4DED-99C0-239779F57D5D}
......
#include "../../jlib/base/logging.h"
int main()
{
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" 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>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{3E322E9F-E560-4300-AFF8-1DCE44E7DDA2}</ProjectGuid>
<RootNamespace>testlogging</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</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>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<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|x64'">
<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|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(BOOST);$(DEVLIBS)\jlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="test_logging.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<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>
</ItemGroup>
<ItemGroup>
<ClCompile Include="test_logging.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>
\ No newline at end of file
#include "../../jlib/win32/registry.h"
#include <exception>
#include <iostream>
using namespace std;
using namespace jlib::win32::reg;
int main()
{
constexpr int kExitError = 1;
try
{
wcout << L"=========================================\n";
wcout << L"*** Testing Giovanni Dicanio's WinReg ***\n";
wcout << L"=========================================\n\n";
//
// Test subkey and value enumeration
//
const wstring testSubKey = L"SOFTWARE\\GioTest";
RegKey key;
key.open(HKEY_CURRENT_USER, testSubKey);
vector<wstring> subKeyNames = key.querySubKeys();
wcout << L"Subkeys:\n";
for (const auto& s : subKeyNames)
{
wcout << L" [" << s << L"]\n";
}
wcout << L'\n';
vector<pair<wstring, DWORD>> values = key.queryValues();
wcout << L"Values:\n";
for (const auto& v : values)
{
wcout << L" [" << v.first << L"](" << RegKey::regTypeToString(v.second) << L")\n";
}
wcout << L'\n';
key.close();
//
// Test SetXxxValue and GetXxxValue methods
//
key.open(HKEY_CURRENT_USER, testSubKey);
const DWORD testDw = 0x1234ABCD;
const ULONGLONG testQw = 0xAABBCCDD11223344;
const wstring testSz = L"CiaoTestSz";
const wstring testExpandSz = L"%PATH%";
const vector<BYTE> testBinary{ 0xAA, 0xBB, 0xCC, 0x11, 0x22, 0x33 };
const vector<wstring> testMultiSz{ L"Hi", L"Hello", L"Ciao" };
key.setDwordValue(L"TestValueDword", testDw);
key.setQwordValue(L"TestValueQword", testQw);
key.setStringValue(L"TestValueString", testSz);
key.setExpandStringValue(L"TestValueExpandString", testExpandSz);
key.setMultiStringValue(L"TestValueMultiString", testMultiSz);
key.setBinaryValue(L"TestValueBinary", testBinary);
DWORD testDw1 = key.getDwordValue(L"TestValueDword");
if (testDw1 != testDw)
{
wcout << L"RegKey::GetDwordValue failed.\n";
}
DWORD typeId = key.queryValueType(L"TestValueDword");
if (typeId != REG_DWORD)
{
wcout << L"RegKey::QueryValueType failed for REG_DWORD.\n";
}
ULONGLONG testQw1 = key.getQwordValue(L"TestValueQword");
if (testQw1 != testQw)
{
wcout << L"RegKey::GetQwordValue failed.\n";
}
typeId = key.queryValueType(L"TestValueQword");
if (typeId != REG_QWORD)
{
wcout << L"RegKey::QueryValueType failed for REG_QWORD.\n";
}
wstring testSz1 = key.getStringValue(L"TestValueString");
if (testSz1 != testSz)
{
wcout << L"RegKey::GetStringValue failed.\n";
}
typeId = key.queryValueType(L"TestValueString");
if (typeId != REG_SZ)
{
wcout << L"RegKey::QueryValueType failed for REG_SZ.\n";
}
wstring testExpandSz1 = key.getExpandStringValue(L"TestValueExpandString");
if (testExpandSz1 != testExpandSz)
{
wcout << L"RegKey::GetExpandStringValue failed.\n";
}
typeId = key.queryValueType(L"TestValueExpandString");
if (typeId != REG_EXPAND_SZ)
{
wcout << L"RegKey::QueryValueType failed for REG_EXPAND_SZ.\n";
}
vector<wstring> testMultiSz1 = key.getMultiStringValue(L"TestValueMultiString");
if (testMultiSz1 != testMultiSz)
{
wcout << L"RegKey::GetMultiStringValue failed.\n";
}
typeId = key.queryValueType(L"TestValueMultiString");
if (typeId != REG_MULTI_SZ)
{
wcout << L"RegKey::QueryValueType failed for REG_MULTI_SZ.\n";
}
vector<BYTE> testBinary1 = key.getBinaryValue(L"TestValueBinary");
if (testBinary1 != testBinary)
{
wcout << L"RegKey::GetBinaryValue failed.\n";
}
typeId = key.queryValueType(L"TestValueBinary");
if (typeId != REG_BINARY)
{
wcout << L"RegKey::QueryValueType failed for REG_BINARY.\n";
}
//
// Remove some test values
//
key.deleteValue(L"TestValueDword");
key.deleteValue(L"TestValueQword");
key.deleteValue(L"TestValueString");
key.deleteValue(L"TestValueExpandString");
key.deleteValue(L"TestValueMultiString");
key.deleteValue(L"TestValueBinary");
wcout << L"All right!! :)\n\n";
} catch (const RegException& e) {
cout << "\n*** Registry Exception: " << e.what();
cout << "\n*** [Windows API error code = " << e.errorCode();
cout << "\n*** Description: " << e.description() << "\n\n";
return kExitError;
} catch (const exception& e) {
cout << "\n*** ERROR: " << e.what() << '\n';
return kExitError;
}
}
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" 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>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{519E5179-6E95-44EF-A63B-65C9C9C47A3B}</ProjectGuid>
<RootNamespace>testregistry</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</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>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<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|x64'">
<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|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="test_registry.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<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>
</ItemGroup>
<ItemGroup>
<ClCompile Include="test_registry.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>
\ No newline at end of file
#include <Windows.h>
#include <stdio.h>
#include "../../jlib/base/timezone.h"
int main()
{
TIME_ZONE_INFORMATION info = { 0 };
auto ret = GetTimeZoneInformation(&info);
printf("info.bias=%ld\n", info.Bias);
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" 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>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{8A9333D5-2981-4E92-87BF-AFFC5F99B1A4}</ProjectGuid>
<RootNamespace>testtimezone</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</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>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<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|x64'">
<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|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="test_timezone.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<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>
</ItemGroup>
<ItemGroup>
<ClCompile Include="test_timezone.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment