Skip to content

Instantly share code, notes, and snippets.

@TheVice
Last active November 24, 2016 09:54
Show Gist options
  • Save TheVice/7a03bc741cc7213f8749ed1916b151c9 to your computer and use it in GitHub Desktop.
Save TheVice/7a03bc741cc7213f8749ed1916b151c9 to your computer and use it in GitHub Desktop.
Sample wtih HTML deserialization - tags, attributes of tag and style attribute
#include "Attribute.h"
namespace Library
{
namespace HTML
{
std::list<std::pair<Entry, Entry>> Attribute::getAttributes(const std::string& aSource, const Entry& aTag)
{
std::list<std::pair<Entry, Entry>> attributes;
auto offset = std::get<0>(aTag.mLocation);
while (true)
{
offset = aSource.find('=', offset);
if (std::get<1>(aTag.mLocation) < offset)
{
break;
}
auto i = offset - 1;
auto j = i;
bool set = false;
while (i > std::get<0>(aTag.mLocation))
{
if (set && aSource.at(i) == ' ' || aSource.at(i) == '\t')
{
break;
}
else if (!set && aSource.at(i) != ' ' && aSource.at(i) != '\t')
{
j = i;
set = true;
}
--i;
}
const auto attribute_name = Entry(i + 1, j + 1);
i = offset + 1;
j = i;
set = false;
bool gaps_present = false;
while (j < std::get<1>(aTag.mLocation))
{
if (!gaps_present && aSource.at(j) == '\"')
{
gaps_present = true;
i = j;
set = true;
}
else if (gaps_present && aSource.at(j) == '\"')
{
++j;
break;
}
if (set && !gaps_present && aSource.at(j) == ' ' || aSource.at(j) == '\t')
{
break;
}
else if (!set && aSource.at(j) != ' ' && aSource.at(j) != '\t')
{
i = j;
set = true;
}
++j;
}
if (gaps_present && j < aSource.find(':', i))
{
i += 1;
j -= 2;
}
auto attribute_value = Entry(i, j);
attributes.push_back(std::make_pair(attribute_name, attribute_value));
++offset;
}
return attributes;
}
std::list<std::pair<Entry, Entry>> Attribute::getStyleAttribute(const std::string& aSource,
const Entry& aAttributeValue)
{
std::list<std::pair<Entry, Entry>> styleValues;
auto offset = std::get<0>(aAttributeValue.mLocation);
while (true)
{
offset = aSource.find(':', offset);
if (std::get<1>(aAttributeValue.mLocation) < offset)
{
break;
}
auto key_start = aSource.rfind(';', offset);
if (std::string::npos == key_start || key_start < std::get<0>(aAttributeValue.mLocation))
{
key_start = aSource.rfind('\"', offset);
}
if (std::string::npos != key_start && std::get<0>(aAttributeValue.mLocation) <= key_start)
{
auto value_end = aSource.find(';', offset);
if (std::get<1>(aAttributeValue.mLocation) < value_end)
{
value_end = aSource.find('\"', offset);
}
if (value_end < std::get<1>(aAttributeValue.mLocation))
{
const auto key = Entry(key_start + 1, offset);
const auto value = Entry(offset + 1, value_end);
styleValues.push_back(std::make_pair(key, value));
}
}
++offset;
}
return styleValues;
}
}
}
#ifndef _TABLE_TAG_H_
#define _TABLE_TAG_H_
#include "Entry.h"
#include <list>
#include <string>
namespace Library
{
namespace HTML
{
/** Class that handle operations with tag attributes */
class Attribute
{
public:
/** Get attributes from tag source code
*/
static std::list<std::pair<Entry, Entry>> getAttributes(const std::string& aSource, const Entry& aTag);
/** Get style key value
*/
static std::list<std::pair<Entry, Entry>> getStyleAttribute(const std::string& aSource,
const Entry& aAttributeValue);
};
}
}
#endif
cmake_minimum_required(VERSION 2.8.12)
project("test_task")
# main_program
file(GLOB SRC_Files ${CMAKE_CURRENT_SOURCE_DIR}/*.h ${CMAKE_CURRENT_SOURCE_DIR}/*.c ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
add_executable(main_program ${SRC_Files})
# Flags
if(MSVC)
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(FLAGS "${FLAGS} -Wall -Wextra -Werror")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${DEFAULT_CMAKE_C_FLAGS} ${FLAGS} -std=c11")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${DEFAULT_CMAKE_CXX_FLAGS} ${FLAGS} -std=c++1y")
add_definitions(-D__clang__)
else()
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /EHsc /W4")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /EHsc /W4")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /EHsc /W0 /GS")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /EHsc /W0 /GS")
if(CMAKE_CL_64)
set(LINK_FLAGS_RELEASE "${LINK_FLAGS_RELEASE} /DynamicBase /NXCompat")
else()
set(LINK_FLAGS_RELEASE "${LINK_FLAGS_RELEASE} /SafeSEH /DynamicBase /NXCompat")
endif()
endif()
else()
set(FLAGS "${FLAGS} -Wall -Wextra -Werror")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${DEFAULT_CMAKE_C_FLAGS} ${FLAGS} -std=c11")
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${DEFAULT_CMAKE_CXX_FLAGS} ${FLAGS} -std=c++1y")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${DEFAULT_CMAKE_CXX_FLAGS} ${FLAGS} -std=c++14")
endif()
endif()
#ifndef _ENTRY_H_
#define _ENTRY_H_
#include <string>
#include <ostream>
#include <utility>
namespace Library
{
namespace HTML
{
struct Entry
{
Entry()
: mLocation(std::make_pair(std::string::npos, std::string::npos))
{
}
Entry(size_t aStartPosition, size_t aEndPosition)
: mLocation(std::make_pair(aStartPosition, aEndPosition))
{
}
Entry(const std::pair<size_t, size_t>& aLocation)
: mLocation(aLocation)
{
}
std::string GetRecord(const std::string& aSource) const
{
if (aSource.empty() || std::get<0>(mLocation) > aSource.size())
{
return std::string("");
}
return aSource.substr(std::get<0>(mLocation), std::get<1>(mLocation) - std::get<0>(mLocation));
}
bool empty() const
{
return (std::string::npos == std::get<0>(mLocation) || std::string::npos == std::get<1>(mLocation));
}
friend std::ostream& operator<<(std::ostream& aOutput, const Entry& aEntry)
{
aOutput << "{" << std::get<0>(aEntry.mLocation) << " " << std::get<1>(aEntry.mLocation) << "}";
return aOutput;
}
const std::pair<size_t, size_t> mLocation;
};
}
}
#endif
#include "Utility.h"
#include "Page.h"
#include <memory>
#include <iostream>
#ifdef WIN32
#include <tchar.h>
#else
#define _tmain
#define _TCHAR char
#endif
#ifndef _MSC_VER
int main(int argc, _TCHAR* argv[])
#else
int _tmain(int argc, _TCHAR* argv[])
#endif
{
std::string file_path;
if (argc > 1)
{
#ifdef UNICODE
const auto length = std::wcslen(argv[1]);
file_path.reserve(1 + length);
file_path.resize(1 + length);
Library::Utility::wchar2char(argv[1], &file_path.front(), static_cast<int>(length));
#else
file_path = argv[1];
#endif
}
else
{
#ifdef NDEBUG
#ifdef UNICODE
std::wcerr << L"Bad using of Release build. Use next: " << argv[0] << L" <path to input file>" << std::endl;
#else
std::cerr << "Bad using of Release build. Use next: " << argv[0] << " <path to input file>" << std::endl;
#endif
return -1;
#else
file_path = Library::Utility::getPathToInputFile();
#endif
}
std::string file_content;
Library::Utility::readFile(file_path, file_content);
if (file_content.empty())
{
std::cerr << file_path.c_str() << " is empty or absent. Exit." << std::endl;
return -1;
}
const auto page = std::make_unique<Library::HTML::Page>(file_content);
std::cout << (*page.get()) << std::endl;
return 0;
}
#include "Page.h"
#include "Tag.h"
#include "Attribute.h"
namespace Library
{
namespace HTML
{
Page::Page(const std::string& aPageSource)
: mPageSource(aPageSource)
, mElements()
{
// Get tags from input
const auto tags = Library::HTML::Tag::getTags(aPageSource);
// If no tags present end work in constructor
if (tags.empty())
{
return;
}
// Reserve space for desiarilized objects
mElements.reserve(tags.size());
// Walk for tags
for (const auto& tag : tags)
{
// Get name for tag
const auto tagName = Library::HTML::Tag::getTagName(mPageSource, tag);
// If unable to get tag name continue with other
if (tagName.empty())
{
continue;
}
// Get attributes for tag
const auto attributes = Library::HTML::Attribute::getAttributes(mPageSource, tag);
bool added = false;
// Walk for attribute
for (const auto& attribute : attributes)
{
// Get style attribute
const auto styleAttribute = Library::HTML::Attribute::getStyleAttribute(mPageSource, std::get<1>(attribute));
// If style attribute present added all attributes and style attributes
if (!styleAttribute.empty())
{
std::map<std::string, std::string> attributes_;
for (const auto& attribute_ : attributes)
{
attributes_.insert(make_pair(std::get<0>(attribute_).GetRecord(mPageSource),
std::get<1>(attribute_).GetRecord(mPageSource)));
}
std::map<std::string, std::string> styleAttribute_;
for (const auto& key_value : styleAttribute)
{
styleAttribute_.insert(make_pair(std::get<0>(key_value).GetRecord(mPageSource),
std::get<1>(key_value).GetRecord(mPageSource)));
}
PageElement element(tagName.GetRecord(mPageSource), attributes_, styleAttribute_);
mElements.push_back(element);
added = true;
break;
}
}
// If no style attribute present added all attributes without style attribute
if (!added)
{
std::map<std::string, std::string> attributes_;
for (const auto& attribute : attributes)
{
attributes_.insert(make_pair(std::get<0>(attribute).GetRecord(mPageSource),
std::get<1>(attribute).GetRecord(mPageSource)));
}
PageElement element(tagName.GetRecord(mPageSource), attributes_);
mElements.push_back(element);
}
}
}
Page::~Page()
{
}
std::ostream& operator<<(std::ostream& aOutput, const Page& aPage)
{
for (const auto& element : aPage.mElements)
{
aOutput << element;
}
return aOutput;
}
}
}
#ifndef _PAGE_H_
#define _PAGE_H_
#include <map>
#include <string>
#include <vector>
#include <ostream>
namespace Library
{
namespace HTML
{
/** Structure that hold source of page element - tag */
struct PageElement
{
/** Initializes page element
* @param aName Name of page element
* @param aAttributes Attributes of page element
*/
PageElement(const std::string& aName,
const std::map<std::string, std::string>& aAttributes)
: mName(aName)
, mAttributes(aAttributes)
, mStyleAttribute()
{
}
/** Initializes page element
* @param aName Name of page element
* @param aAttributes Attributes of page element
* @param aStyleAttribute Style attribute of page element
*/
PageElement(const std::string& aName,
const std::map<std::string, std::string>& aAttributes,
const std::map<std::string, std::string>& aStyleAttribute)
: mName(aName)
, mAttributes(aAttributes)
, mStyleAttribute(aStyleAttribute)
{
}
/** Name of element */
const std::string mName;
/** Attributes of element */
const std::map<std::string, std::string> mAttributes;
/** Style attribute of element */
const std::map<std::string, std::string> mStyleAttribute;
/** Format text output of containce data
* @param aOutput Argument reference to std::ostream object
* @param aPageElement Argument reference to PageElement object
* @returns std::ostream object with added information about PageElement object
*/
friend std::ostream& operator<<(std::ostream& aOutput, const PageElement& aPageElement)
{
aOutput << aPageElement.mName << std::endl;
for (const auto& attribute : aPageElement.mAttributes)
{
aOutput << "\t" << std::get<0>(attribute) << std::endl;
if (std::get<0>(attribute) == "style")
{
for (const auto& key_value : aPageElement.mStyleAttribute)
{
aOutput << "\t\t" << std::get<0>(key_value) << std::endl << "\t\t\t" << std::get<1>(key_value) << std::endl;
}
}
else
{
aOutput << "\t\t" << std::get<1>(attribute) << std::endl;
}
}
return aOutput;
}
};
/** Class hold source code of input and desiarilized objects */
class Page
{
public:
/** Initializes page: hold source code and desiarilized it to objects
* @param aPageSource Source of input
*/
Page(const std::string& aPageSource);
/** Free objects and source */
virtual ~Page();
public:
/** Prohibited default constructor */
Page() = delete;
/** Prohibited copy constructor
* @param aRhs Reference to Page object
*/
Page(const Page& aRhs) = delete;
/** Prohibited assigned operator
* @param aRhs Reference to Page object
* @returns Reference to Page object
*/
Page& operator = (const Page& aRhs) = delete;
public:
/** Format text output of containce data
* @param aOutput Argument reference to std::ostream object
* @param aPage Argument reference to Page object
* @returns std::ostream object with added information about Page object. If object does not containce any elements std::ostream object will be untouchable
*/
friend std::ostream& operator<<(std::ostream& aOutput, const Page& aPage);
private:
/** Source of input */
const std::string mPageSource;
/** Desiarilized input */
std::vector<PageElement> mElements;
};
}
}
#endif
#include "Tag.h"
namespace Library
{
namespace HTML
{
Entry Tag::getTag(const std::string& aSource, size_t aOffset)
{
const auto startPosition = aSource.find('<', aOffset);
if (std::string::npos == startPosition)
{
return Entry();
}
const auto endPosition = aSource.find('>', startPosition);
if (std::string::npos == endPosition)
{
return Entry();
}
return Entry(startPosition, endPosition);
}
std::vector<Entry> Tag::getTags(const std::string& aSource)
{
std::vector<Entry> tags(1 + aSource.size() / 3);
tags.clear();
auto offset = static_cast<size_t>(0);
while (true)
{
const auto tag = getTag(aSource, offset);
offset = std::get<1>(tag.mLocation);
if (std::string::npos == offset)
{
break;
}
tags.push_back(tag);
}
return tags;
}
Entry Tag::getTagName(const std::string& aSource, const Entry& aTagEntry)
{
if (aSource.at(std::get<0>(aTagEntry.mLocation)) != '<' ||
aSource.at(std::get<1>(aTagEntry.mLocation)) != '>')
{
return Entry();
}
auto endPosition = aSource.find(' ', std::get<0>(aTagEntry.mLocation));
if (std::get<1>(aTagEntry.mLocation) < endPosition)
{
endPosition = std::get<1>(aTagEntry.mLocation);
}
// Check is this close tag
auto closeTagPosition = aSource.find('/', std::get<0>(aTagEntry.mLocation));
if (closeTagPosition <= endPosition)
{
return Entry();
}
return Entry(std::get<0>(aTagEntry.mLocation) + 1, endPosition);
}
}
}
#ifndef _TAG_H_
#define _TAG_H_
#include "Entry.h"
#include <vector>
#include <string>
namespace Library
{
namespace HTML
{
/** Class that handle operations with tags */
class Tag
{
public:
/** Get tag from input source code
*/
static Entry getTag(const std::string& aSource, size_t aOffset = 0);
/** Get tags from input source code
*/
static std::vector<Entry> getTags(const std::string& aSource);
/** Get name of tag
*/
static Entry getTagName(const std::string& aSource, const Entry& aTagEntry);
};
}
}
#endif
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Express 14 for Windows Desktop
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_task", ".\test_task.vcxproj", "{D2406261-E7E0-4F61-8F86-9C50B4F284DD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D2406261-E7E0-4F61-8F86-9C50B4F284DD}.Debug|Win32.ActiveCfg = Debug|Win32
{D2406261-E7E0-4F61-8F86-9C50B4F284DD}.Debug|Win32.Build.0 = Debug|Win32
{D2406261-E7E0-4F61-8F86-9C50B4F284DD}.Debug|x64.ActiveCfg = Debug|x64
{D2406261-E7E0-4F61-8F86-9C50B4F284DD}.Debug|x64.Build.0 = Debug|x64
{D2406261-E7E0-4F61-8F86-9C50B4F284DD}.Release|Win32.ActiveCfg = Release|Win32
{D2406261-E7E0-4F61-8F86-9C50B4F284DD}.Release|Win32.Build.0 = Release|Win32
{D2406261-E7E0-4F61-8F86-9C50B4F284DD}.Release|x64.ActiveCfg = Release|x64
{D2406261-E7E0-4F61-8F86-9C50B4F284DD}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.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="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{D2406261-E7E0-4F61-8F86-9C50B4F284DD}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>test_task</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</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 Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<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 Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<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>
<OutDir>$(ProjectDir)bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(ProjectDir)bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(ProjectDir)bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(ProjectDir)bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="Attribute.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="Page.cpp" />
<ClCompile Include="Tag.cpp" />
<ClCompile Include="Utility.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Attribute.h" />
<ClInclude Include="Entry.h" />
<ClInclude Include="Page.h" />
<ClInclude Include="Tag.h" />
<ClInclude Include="Utility.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
<?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;xsd</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Attribute.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Page.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Tag.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Utility.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Attribute.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Entry.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Page.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Tag.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Utility.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>
#include "Utility.h"
#ifdef WIN32
#include <windows.h>
#endif
namespace Library
{
namespace Utility
{
std::streamoff readFile(const char* aFileName, std::string& aFileContent)
{
return readFile(std::string(aFileName), aFileContent);
}
std::streamoff readFile(const std::string& aFileName, std::string& aFileContent)
{
aFileContent.clear();
std::ifstream file(aFileName, std::fstream::binary);
if (file)
{
file.seekg(0, std::fstream::end);
const std::streamoff length = file.tellg();
if (!length)
{
file.close();
return length;
}
file.seekg(0, std::fstream::beg);
aFileContent.reserve(static_cast<std::string::size_type>(length));
aFileContent.resize(static_cast<std::string::size_type>(length));
file.read(&aFileContent.front(), length);
file.close();
return length;
}
return 0;
}
std::string getPathToInputFile()
{
std::string file_path(__FILE__);
#ifdef WIN32
auto offset = file_path.rfind("\\");
#else
auto offset = file_path.rfind("/");
#endif
if (offset != std::string::npos && offset > 0)
{
offset -= 1;
#ifdef WIN32
offset = file_path.rfind("\\", offset);
#else
offset = file_path.rfind("/", offset);
#endif
if (offset != std::string::npos && offset > 0)
{
file_path = file_path.substr(0, offset);
#ifdef WIN32
file_path.append("\\input\\input.html");
#else
file_path.append("/input/input.html");
#endif
}
else
{
file_path.clear();
}
}
else
{
file_path.clear();
}
return file_path;
}
#ifdef WIN32
void char2wchar(const char* aChar, wchar_t* aWchar, int aLength)
{
if (aLength <= 0 || !aChar || !aWchar)
{
return;
}
MultiByteToWideChar(CP_ACP, 0, aChar, aLength, aWchar, aLength);
}
void wchar2char(const wchar_t* aWchar, char* aChar, int aLength)
{
if (aLength <= 0 || !aChar || !aWchar)
{
return;
}
static const char defaultChar = '?';
BOOL usedDefaultChar = FALSE;
WideCharToMultiByte(CP_ACP, 0, aWchar, aLength, aChar, aLength, &defaultChar, &usedDefaultChar);
}
#endif
}
}
#ifndef _UTILITY_H_
#define _UTILITY_H_
#include <string>
#include <fstream>
namespace Library
{
namespace Utility
{
/** Get file size and read it content to second argument
* @param aFileName file path
* @param aFileContent reference to object where to store file content
* @returns std::streamoff file length. For empty or file that unable to read return zero
*/
std::streamoff readFile(const char* aFileName, std::string& aFileContent);
/** Get file size and read it content to second argument
* @param aFileName file path
* @param aFileContent reference to object where to store file content
* @returns std::streamoff file length. For empty or file that unable to read return zero
*/
std::streamoff readFile(const std::string& aFileName, std::string& aFileContent);
/** Get hardcoded path to input file
* @returns std::string Hardcoded path to input file in Debug mode and empty std::string in Release mode
*/
std::string getPathToInputFile();
#ifdef WIN32
/** Convert from char to wide char array
* @param aChar input char array
* @param aWchar output wide char array
* @param aLength length of array
*/
void char2wchar(const char* aChar, wchar_t* aWchar, int aLength);
/** Convert from wide char to char array
* @param aWchar input wide char array
* @param aChar output char array
* @param aLength length of array
*/
void wchar2char(const wchar_t* aWchar, char* aChar, int aLength);
#endif
}
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment