Commit 76d236e3 authored by Chuck Walbourn's avatar Chuck Walbourn
Browse files

Added Xbox One XDK samples

parent debd423c
Loading
Loading
Loading
Loading

Kits/ATGTK/CSVReader.h

0 → 100644
+288 −0
Original line number Diff line number Diff line
//--------------------------------------------------------------------------------------
// File: CSVReader.h
//
// Simple parser for .csv (Comma-Separated Values) files.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//-------------------------------------------------------------------------------------

#pragma once

#include <exception>
#include <memory>
#include <vector>


namespace DX
{
    class CSVReader
    {
    public:
        enum class Encoding
        {
            ANSI,   // File is ANSI (codepage 1252)
            UTF16,  // File is Unicode UTF-16
            UTF8,   // File is Unicode UTF-8
        };

        explicit CSVReader(_In_z_ const wchar_t* fileName, Encoding encoding = Encoding::ANSI, bool ignoreComments = false) :
            m_end(nullptr),
            m_currentChar(nullptr),
            m_currentLine(0),
            m_ignoreComments(ignoreComments)
        {
            assert(fileName != 0);

#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)
            ScopedHandle hFile(safe_handle(CreateFile2(fileName,
                GENERIC_READ,
                FILE_SHARE_READ,
                OPEN_EXISTING,
                nullptr)));
#else
            ScopedHandle hFile(safe_handle(CreateFileW(fileName,
                GENERIC_READ,
                FILE_SHARE_READ,
                nullptr,
                OPEN_EXISTING,
                FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
                nullptr)));
#endif
            if (!hFile)
            {
                throw std::exception("CreateFile");
            }

            FILE_STANDARD_INFO fileInfo;
            if (!GetFileInformationByHandleEx(hFile.get(), FileStandardInfo, &fileInfo, sizeof(fileInfo)))
            {
                throw std::exception("GetFileInformationByHandleEx");
            }

            if (fileInfo.EndOfFile.HighPart > 0 || fileInfo.EndOfFile.LowPart > 0x7ffffffd)
            {
                // File is 2 GBs or larger
                throw std::exception("CSV too large");
            }

            std::unique_ptr<uint8_t[]> data(new uint8_t[fileInfo.EndOfFile.LowPart + 2]);

            DWORD out;
            if (!ReadFile(hFile.get(), data.get(), fileInfo.EndOfFile.LowPart, &out, nullptr)
                || out != fileInfo.EndOfFile.LowPart)
            {
                throw std::exception("ReadFile");
            }

            // Ensure buffer is nul terminated
            data[out] = data[out + 1] = '\0';

            // Ignore lines in .csv that start with '#' character

            // Handle text encoding
            if (encoding == Encoding::UTF16)
            {
                m_data.reset(reinterpret_cast<wchar_t*>(data.release()));
                m_end = reinterpret_cast<wchar_t*>(&data[out]);
            }
            else
            {
                // If we are not UTF16, we have to convert...
                UINT cp = (encoding == Encoding::UTF8) ? CP_UTF8 : 1252;

                int cch = ::MultiByteToWideChar(cp, 0, reinterpret_cast<LPCSTR>(data.get()), -1, nullptr, 0);

                if (cch <= 0)
                {
                    throw std::exception("MultiByteToWideChar");
                }

                m_data.reset(new wchar_t[cch]);

                int result = ::MultiByteToWideChar(cp, 0, reinterpret_cast<LPCSTR>(data.get()), -1, m_data.get(), cch);

                if (result <= 0)
                {
                    m_data.reset();
                    throw std::exception("MultiByteToWideChar");
                }

                m_end = &m_data[result - 1];
            }

            // Locate the start of lines
            bool newline = true;
            for (const wchar_t* ptr = m_data.get(); *ptr != 0 && ptr < m_end; )
            {
                if (*ptr == '\n' || *ptr == '\r')
                {
                    ++ptr;
                    newline = true;
                }
                else if (*ptr == '#' && m_ignoreComments && newline)
                {
                    // Skip to CR
                    for (; *ptr != 0 && *ptr != '\n' && ptr < m_end; ++ptr) {}
                }
                else if (*ptr == '"')
                {
                    if (newline)
                    {
                        m_lines.push_back(ptr);
                        newline = false;
                    }

                    // Skip to next " (skipping "" escapes)
                    for (ptr++; *ptr != 0 && ptr < m_end; ++ptr)
                    {
                        if (*ptr == '"')
                        {
                            ++ptr;
                            if (*ptr != '"')
                                break;
                        }
                    }
                }
                else if (newline)
                {
                    m_lines.push_back(ptr);
                    newline = false;
                    ++ptr;
                }
                else
                    ++ptr;
            }

            TopOfFile();
        }

        CSVReader(const CSVReader&) = delete;
        CSVReader& operator=(const CSVReader&) = delete;

        // Return number of lines of data in CSV
        size_t GetRecordCount() const { return m_lines.size(); }

        // Check for end of file
        bool EndOfFile() const { return m_currentChar == nullptr; }

        // Return current record number (0-based)
        size_t RecordIndex() const { return m_currentLine; }

        // Set to top of file
        void TopOfFile()
        {
            m_currentChar = (m_lines.empty()) ? nullptr : m_lines[0];
            m_currentLine = 0;
        }

        // Start processing next record (returns false when out of data)
        bool NextRecord()
        {
            if (!m_currentChar)
                return false;

            if (++m_currentLine >= m_lines.size())
            {
                m_currentChar = nullptr;
                return false;
            }

            m_currentChar = m_lines[m_currentLine];

            return true;
        }

        // Get next item in record (returns false when reached end of record)
        bool NextItem(_Out_writes_(maxstr) wchar_t* str, _In_ size_t maxstr)
        {
            if (!str || !m_currentChar || !maxstr)
                return false;

            *str = L'\0';

            const wchar_t* end = ((m_currentLine + 1) >= m_lines.size()) ? m_end : (m_lines[(m_currentLine + 1)]);

            if (m_currentChar >= end)
                return false;

            wchar_t* dest = str;
            wchar_t* edest = str + maxstr;

            for (const wchar_t* ptr = m_currentChar; ; )
            {
                if (*ptr == 0 || ptr >= end || *ptr == '\n' || *ptr == '\r')
                {
                    m_currentChar = end;
                    break;
                }
                else if (*ptr == ',')
                {
                    m_currentChar = ptr + 1;
                    break;
                }
                else if (*ptr == '\t' || *ptr == ' ')
                {
                    // Whitespace
                    ++ptr;
                }
                else if (*ptr == '"')
                {
                    // Copy from " to ", respecting "" as double-quotes
                    for (ptr++; *ptr != 0 && ptr < end; ++ptr)
                    {
                        if (*ptr == '"')
                        {
                            ++ptr;
                            if (*ptr != '"')
                                break;
                            else if (dest < edest)
                                *(dest++) = '"';
                        }
                        else if (dest < edest)
                            *(dest++) = *ptr;
                    }
                }
                else
                {
                    for (; *ptr != 0 && ptr < end; ++ptr)
                    {
                        if (*ptr == '\n' || *ptr == '\r' || *ptr == ',')
                            break;
                        else if (dest < edest)
                            *(dest++) = *ptr;
                    }
                }
            }

            if (dest < edest)
                *dest = 0;

            return true;
        }

        template<size_t TNameLength>
        bool NextItem(wchar_t(&name)[TNameLength])
        {
            return NextItem(name, TNameLength);
        }

    private:
        struct handle_closer { void operator()(HANDLE h) { if (h) CloseHandle(h); } };

        typedef std::unique_ptr<void, handle_closer> ScopedHandle;

        inline HANDLE safe_handle(HANDLE h) { return (h == INVALID_HANDLE_VALUE) ? 0 : h; }

        std::unique_ptr<wchar_t[]>  m_data;
        const wchar_t*              m_end;
        const wchar_t*              m_currentChar;
        size_t                      m_currentLine;
        bool                        m_ignoreComments;
        std::vector<const wchar_t*> m_lines;
    };
}
+159 −0
Original line number Diff line number Diff line
//--------------------------------------------------------------------------------------
// CommandLineHelpers.cpp
//
// Advanced Technology Group (ATG)
// Copyright (C) Microsoft Corporation. All rights reserved.
//--------------------------------------------------------------------------------------
#include "pch.h"

#include "CommandLineHelpers.h"
#include <algorithm>

using namespace ATG;

const wchar_t *ATG::ConsumeDigits(const wchar_t *value)
{
    if (value == nullptr) return nullptr;
    const wchar_t *result = value;

    while (iswxdigit(*result))
    {
        ++result;
    }

    return result;
}

#if defined(_XBOX_ONE) && defined(_TITLE)
ATG::WCRANGE ATG::MakeRange(wchar_t c0, wchar_t c1)
#else
WCRANGE ATG::MakeRange(wchar_t c0, wchar_t c1)
#endif
{
    uint32_t u0 = std::min(c0, c1);
    uint32_t u1 = std::max(c0, c1);
    uint32_t count = u1 - u0 + 1;

    WCRANGE result = { c0, wchar_t(std::min(count, uint32_t(0xFFFF))) };

    return result;
}

bool ATG::ParseCharacterRegion(const wchar_t *rangeSpec, std::vector<WCRANGE> &regions)
{
    {
        const wchar_t *charRange = rangeSpec;

        if (!*charRange) return false;

        wchar_t c0 = *charRange++;
        if (!*charRange)
        {
            // Only one character specified -- but that's OK
            WCRANGE range = { c0, 1 };
            regions.push_back(range);
            return true;
        }

        if (*charRange++ == '-')
        {
            wchar_t c1 = *charRange++;
            if (!c1)
            {
                wprintf(L"Expected another character after '-' when parsing range\n");
                return false;
            }

            if (*charRange)
            {
                wprintf(L"Unexpected character (%c) after parsing range\n", *charRange);
                return false;
            }

            regions.push_back(MakeRange(c0, c1));
            return true;
        }
    }

    {
        const wchar_t *hexRange = rangeSpec;

        // Match and consume the hex prefix '0x'
        if (_wcsnicmp(L"0x", hexRange, 2) != 0)
        {
            wprintf(L"Expected a hexidecimal range specification\n");
            return false;
        }
        hexRange += 2;

        unsigned c0 = 0;
        // Scan the hex value
        if (swscanf_s(hexRange, L"%lx", &c0) != 1)
        {
            wprintf(L"Expected a hexidecimal value following the prefix ('0x')\n");
            return false;
        }
        hexRange = ConsumeDigits(hexRange);

        if (c0 > 0xFFFF)
        {
            wprintf(L"The first hexidecimal value in the range specification is too large (0x%X)\n", c0);
            return false;
        }

        if (!*hexRange)
        {
            // Only one hex value specified -- but that's OK
            WCRANGE range = { wchar_t(c0), 1 };
            regions.push_back(range);
            return true;
        }

        if (*hexRange++ == '-')
        {
            if (!*hexRange)
            {
                wprintf(L"Expected another hexidecimal value after '-' when parsing range\n");
                return false;
            }

            // Match and consume the hex prefix '0x'
            if (_wcsnicmp(L"0x", hexRange, 2) != 0)
            {
                wprintf(L"Second part of the hexidecimal range specification doesn't doesn't start with the '0x' hexidecimal prefix (%s)\n", hexRange);
                return false;
            }
            hexRange += 2;

            unsigned c1 = 0;
            // Scan the hex value
            if (swscanf_s(hexRange, L"%lx", &c1) != 1)
            {
                wprintf(L"Expected a hexidecimal value following the prefix ('0x')\n");
                return false;
            }
            hexRange = ConsumeDigits(hexRange);

            if (c1 > 0xFFFF)
            {
                wprintf(L"The second hexidecimal value in the range specification is too large (0x%X)\n", c1);
                return false;
            }

            if (*hexRange)
            {
                wprintf(L"Unexpected character (%c) after parsing the second value in the range specification\n", *hexRange);
                return false;
            }

            regions.push_back(MakeRange(wchar_t(c0), wchar_t(c1)));
            return true;

        }
        else
        {
            wprintf(L"Expecting one or two hexidecimal values (4 digits or less) separated by a dash\n");
            return false;
        }
    }
}
+96 −0
Original line number Diff line number Diff line
//--------------------------------------------------------------------------------------
// CommandLineHelpers.h
//
// Advanced Technology Group (ATG)
// Copyright (C) Microsoft Corporation. All rights reserved.
//--------------------------------------------------------------------------------------
#pragma once

#include <vector>

namespace ATG
{
    struct SValue
    {
        const wchar_t *name;
        unsigned value;
    };


    template<size_t _SIZE>
    inline bool LookupByName(const wchar_t *name, const SValue(&table)[_SIZE], unsigned &result)
    {
        for (int i = 0; i < _SIZE; ++i)
        {
            if (!_wcsicmp(name, table[i].name))
            {
                result = table[i].value;
                return true;
            }
        }
        return false;
    }

    template<size_t _SIZE>
    inline const wchar_t *LookupByValue(unsigned value, const SValue(&table)[_SIZE])
    {
        for (int i = 0; i < _SIZE; ++i)
        {
            if (value == table[i].value)
                return table[i].name;
        }

        return L"";
    }

    template<size_t _SIZE>
    inline bool ParseTableValue(unsigned option, const wchar_t *name, const SValue(&table)[_SIZE], unsigned &result)
    {
        const wchar_t pleaseUseMsg[] = L"Please use one of the following: ";

        if (!LookupByName(name, table, result))
        {
            wprintf(L"Invalid value specified with -%ls (%ls)\n", LookupByValue(option, g_Options), name);
            wprintf(pleaseUseMsg);
            PrintTable(_countof(pleaseUseMsg) - 1, table);
            wprintf(L"\n\n");
            return false;
        }
        return true;
    }

    template<size_t _SIZE>
    inline void PrintTable(size_t indent, const SValue(&table)[_SIZE])
    {
        size_t idt = indent;
        for (int i = 0; i < _SIZE; ++i)
        {
            size_t cchName = wcslen(table[i].name);

            if (idt + cchName + 2 >= 80)
            {
                wprintf(L"\n");
                for (idt = 0; idt < indent; ++idt) wprintf(L" ");
            }

            wprintf(L"%ls ", table[i].name);
            idt += cchName + 2;
        }

        wprintf(L"\n");
    }

    const wchar_t *ConsumeDigits(const wchar_t *value);

#if defined(_XBOX_ONE) && defined(_TITLE)
    typedef struct tagWCRANGE
    {
        WCHAR  wcLow;
        USHORT cGlyphs;
} WCRANGE, *PWCRANGE, FAR *LPWCRANGE;
#endif
    WCRANGE MakeRange(wchar_t c0, wchar_t c1);

    bool ParseCharacterRegion(const wchar_t *rangeSpec, std::vector<WCRANGE> &regions);

} // namespace ATG
+77 −0
Original line number Diff line number Diff line
//--------------------------------------------------------------------------------------
// FileHelpers.h
//
// Advanced Technology Group (ATG)
// Copyright (C) Microsoft Corporation. All rights reserved.
//--------------------------------------------------------------------------------------
#pragma once

#include <fileapi.h>
#include <assert.h>
#include <stdio.h>

#include <wrl/client.h>

namespace ATG
{
    class auto_delete_file
    {
    public:
        auto_delete_file(HANDLE hFile) : m_handle(hFile) {}

        auto_delete_file(const auto_delete_file&) = delete;
        auto_delete_file& operator=(const auto_delete_file&) = delete;

        ~auto_delete_file()
        {
            if (m_handle)
            {
                FILE_DISPOSITION_INFO info = {};
                info.DeleteFile = TRUE;
                BOOL b = true;
                b = SetFileInformationByHandle(m_handle, FileDispositionInfo, &info, static_cast<DWORD>(sizeof(info)));
#ifdef _DEBUG
                if (!b)
                {
                    DWORD error = GetLastError();
                    wchar_t buff[128] = {};
                    swprintf_s(buff, L"ERROR: SetFileInformationByHandle failed (0x%08X)\n", error);
                    OutputDebugStringW(buff);
                }
#endif
                assert(b);
            }
        }

        void clear() { m_handle = 0; }

    private:
        HANDLE m_handle;
    };

#ifdef __IWICStream_FWD_DEFINED__
    class auto_delete_file_wic
    {
    public:
        auto_delete_file_wic(Microsoft::WRL::ComPtr<IWICStream>& hFile, LPCWSTR szFile) : m_handle(hFile), m_filename(szFile) {}

        auto_delete_file_wic(const auto_delete_file_wic&) = delete;
        auto_delete_file_wic& operator=(const auto_delete_file_wic&) = delete;

        ~auto_delete_file_wic()
        {
            if (m_filename)
            {
                m_handle.Reset();
                DeleteFileW(m_filename);
            }
        }

        void clear() { m_filename = 0; }

    private:
        LPCWSTR m_filename;
        Microsoft::WRL::ComPtr<IWICStream>& m_handle;
    };
#endif
}
 No newline at end of file
+23 −0
Original line number Diff line number Diff line
//--------------------------------------------------------------------------------------
// BufferDescriptor.cpp
//
// Advanced Technology Group (ATG)
// Copyright (C) Microsoft Corporation. All rights reserved.
//--------------------------------------------------------------------------------------
#include "pch.h"
#include "BufferDescriptor.h"

using namespace ATG;


void ATG::SetPixel(const BufferDesc & destBuffer, unsigned col, unsigned row, uint8_t clr)
{
    if (col >= destBuffer.width || row >= destBuffer.height)
        return;

    unsigned index = row * (destBuffer.width) + col;
    if (index < destBuffer.size)
    {
        destBuffer.data[index] = clr;
    }
}
 No newline at end of file
Loading