diff --git a/.devzone/build/files b/.devzone/build/files deleted file mode 100644 index dd256432..00000000 --- a/.devzone/build/files +++ /dev/null @@ -1,2 +0,0 @@ -R;%{RPMBUILDDIR}/RPMS/%{ARCH}/*.%{ARCH}.rpm -5;%{RPMBUILDDIR}/SRPMS/*.src.rpm diff --git a/.devzone/build/grfcodec.spec b/.devzone/build/grfcodec.spec deleted file mode 100644 index d6f378f2..00000000 --- a/.devzone/build/grfcodec.spec +++ /dev/null @@ -1,54 +0,0 @@ -Name: %{dz_repo} -Version: 999.%{dz_version} -Release: %{_vendor}%{?suse_version} -Summary: A suite of programs to develop NewGRFs -Group: Development/Tools/Building -License: GPLv2+ -URL: http://dev.openttdcoop.org/projects/grfcodec -Source0: %{name}-%{dz_version}.tar - -BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot - -BuildRequires: gcc-c++ -BuildRequires: boost-devel > 1.36 -BuildRequires: libpng-devel - -Provides: nforenum = %{version} -Obsoletes: nforenum < %{version} - -#We need Mercurial for auto version detection: (not needed with source tarball) -BuildRequires: mercurial - -%description -A suite of programs to modify Transport Tycoon Deluxe's GRF files. -Contains GRFCodec for encoding and decoding the actual GRF files, -GRFID for extracting the (unique) NewGRF identifier and NFORenum, -a format correcter and linter for the NFO language. NFO and PCX -or PNG files are encoded to form GRF files. - -%prep -%setup -qn %{name} - -%build -make %{?_smp_mflags} - -%install -make install DESTDIR=%{buildroot} prefix=%{_prefix} - -%clean - -%files -%defattr(-,root,root,-) -%{_bindir}/grfcodec -%{_bindir}/grfid -%{_bindir}/grfstrip -%{_bindir}/nforenum -%dir %{_datadir}/doc/grfcodec -%doc %{_datadir}/doc/grfcodec/COPYING -%doc %{_datadir}/doc/grfcodec/*.txt -%{_mandir}/man1/grfcodec.1* -%{_mandir}/man1/grfid.1* -%{_mandir}/man1/grfstrip.1* -%{_mandir}/man1/nforenum.1* - -%changelog diff --git a/.devzone/build/nightlies/cleanup_days b/.devzone/build/nightlies/cleanup_days deleted file mode 100644 index 573541ac..00000000 --- a/.devzone/build/nightlies/cleanup_days +++ /dev/null @@ -1 +0,0 @@ -0 diff --git a/.devzone/build/nightlies/cleanup_releases b/.devzone/build/nightlies/cleanup_releases deleted file mode 100644 index d00491fd..00000000 --- a/.devzone/build/nightlies/cleanup_releases +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/.devzone/build/nightlies/enable b/.devzone/build/nightlies/enable deleted file mode 100644 index 30c33ac6..00000000 --- a/.devzone/build/nightlies/enable +++ /dev/null @@ -1 +0,0 @@ -libpng diff --git a/.devzone/build/type b/.devzone/build/type deleted file mode 100644 index 916f55df..00000000 --- a/.devzone/build/type +++ /dev/null @@ -1 +0,0 @@ -rpm diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index af14967f..727785eb 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -36,7 +36,7 @@ jobs: echo "::group::Install dependencies" sudo apt-get install -y --no-install-recommends \ - libboost-dev \ + libpng-dev \ # EOF echo "::endgroup::" env: @@ -84,9 +84,7 @@ jobs: - name: Prepare vcpkg run: | ${{ steps.vcpkg.outputs.vcpkg }} install --triplet=${{ matrix.arch }}-osx \ - boost-bimap \ - boost-date-time \ - boost-foreach \ + libpng \ # EOF - name: Install GCC problem matcher @@ -133,9 +131,6 @@ jobs: shell: bash run: | "${{ steps.vcpkg.outputs.vcpkg }}" install --triplet=${{ matrix.arch }}-windows-static \ - boost-bimap \ - boost-date-time \ - boost-foreach \ libpng \ # EOF diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index df688161..4b898513 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -84,9 +84,6 @@ jobs: shell: bash run: | "${{ steps.vcpkg.outputs.vcpkg }}" install --triplet=${{ matrix.arch }}-windows-static \ - boost-bimap \ - boost-date-time \ - boost-foreach \ libpng \ # EOF diff --git a/0compile.txt b/0compile.txt deleted file mode 100644 index e993ccdd..00000000 --- a/0compile.txt +++ /dev/null @@ -1,46 +0,0 @@ -How to compile the GRF development tools ------------------------ - -Compiling the GRF development tools is pretty straightforward. It can be -done, with varying quantities of automation, with Cygwin's gcc (using -Makefile for a cygwin-dependant binary, any Linux gcc (using Makefile, -for a Linux binary). - -GRFCodec and NFORenum require Boost 1.36 or higher. The make system does -not check the Boost version, so compiling with a lower version of Boost -will result in compile failures. - -GRFCodec and NFORenum can optionally be compiled with PNG support. -This requires libpng and zlib to be available. - - -Compiling with make -=================== - -The Makefile will attempt to auto-detect: -- Whether you are building on Cygwin or Linux (ISCYGWIN) -- The location of your boost includes (BOOST_INCLUDE) - -If it gets these wrong, modify Makefile.local appropriately, or set the above -mentioned controlling variables. -ISCYGWIN: 1 on cygwin and 0 on Linux. -BOOST_INCLUDE is the directory where your boost headers can be found. - - -Targets -------- - -The following are the most intersting targets. Other targets exist, but are -less useful. - -all Compile grfcodec, grfid, grfstrip and nforenum - -grfcodec -grfid -grfstrip -nforenum Compile the program in question, using gcc. - -release Compile all programs, then strip and upx them (if enabled) - -clean Delete all compiled files -remake Equivalent of "make clean all" diff --git a/CMakeLists.txt b/CMakeLists.txt index 873c0b3b..729a80ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,7 +57,6 @@ endif() find_package(PNG) -find_package(Boost CONFIG REQUIRED) include(CheckCXXSymbolExists) @@ -120,13 +119,11 @@ add_dependencies(grfstrip version_header) # Create nforenum add_executable(nforenum) add_dependencies(nforenum palettes_header version_header) -target_link_libraries(nforenum Boost::boost) # Create grfcodec add_executable(grfcodec) add_dependencies(grfcodec palettes_header version_header) -target_link_libraries(grfcodec Boost::boost) if(PNG_FOUND) set_target_properties(grfcodec PROPERTIES COMPILE_FLAGS -DWITH_PNG) target_link_libraries(grfcodec PNG::PNG) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fc608845..f0bec505 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -56,7 +56,6 @@ target_sources(nforenum PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/messages.cpp ${CMAKE_CURRENT_SOURCE_DIR}/nforenum.cpp ${CMAKE_CURRENT_SOURCE_DIR}/pseudo.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/pseudo_seq.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rangedint.cpp ${CMAKE_CURRENT_SOURCE_DIR}/sanity.cpp ${CMAKE_CURRENT_SOURCE_DIR}/strings.cpp diff --git a/src/info.cpp b/src/info.cpp index 107ed3a1..d15cefc3 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -26,8 +26,6 @@ int makeint(U8 low, S8 high) void read_file(std::istream&in,int infover,int grfcontversion,std::vector>&sprites); -nfe_map nfo_escapes; - inforeader::inforeader(char *fn, int grfcontversion) { std::ifstream f; @@ -66,7 +64,9 @@ inforeader::inforeader(char *fn, int grfcontversion) if(str == "=") byte--; else if (str[0] == '@') byte = strtol(str.c_str()+1, NULL, 16); - else nfo_escapes.insert(nfe_pair(str, byte++)); + else { + InsertEscape(str, byte++); + } } } getline(f, buffer); // Try again to skip "format: " line @@ -152,25 +152,27 @@ infowriter::infowriter(FILE *info, int useplaintext, const char *directory) fprintf(info,"// (Info version %d)", _useexts ? 32 : 6); if(_useexts) { // (re)insert default escapes - foreach(const esc& e, escapes) - nfo_escapes.insert(nfe_pair(e.str+1, e.byte)); + for (const esc &e : escapes) { + InsertEscape(e.str + 1, e.byte); + } fputs("\n// Escapes:", info); int oldbyte = -1; for (int act = 0; act < 255; act++) { - foreach (const nfe_rpair& p, nfo_escapes.right) { - if (p.second[0] != act) continue; + for (const auto &p : nfo_escapes) { + if (p.first[0] != act) continue; - if (p.first == oldbyte) { + if (p.second == oldbyte) { fprintf(info, " ="); --oldbyte; - } else if (p.first < oldbyte) { + } else if (p.second < oldbyte) { fputs("\n// Escapes:", info); oldbyte = -1; } - while (++oldbyte != p.first) - fprintf(info," %s", nfo_escapes.right.begin()->second.c_str()); - fprintf(info, " %s", p.second.c_str()); + while (++oldbyte != p.second) { + fprintf(info," %s", nfo_escapes[0].first.c_str()); + } + fprintf(info, " %s", p.first.c_str()); } } } diff --git a/src/mapescapes.cpp b/src/mapescapes.cpp index 8844344d..34c1b701 100644 --- a/src/mapescapes.cpp +++ b/src/mapescapes.cpp @@ -1,6 +1,6 @@ /* * mapescapes.cpp - * Helper functions for using boost::bimapped escapes + * Helper functions for using escapes * * Copyright 2009 by Dale McCoy. * @@ -19,6 +19,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include #include @@ -27,37 +28,65 @@ #include "messages.h" #include "mapescapes.h" +nfe_map nfo_escapes; + +void InsertEscape(const std::string &key, int byte) { + auto new_pair = std::make_pair(key, byte); + auto it = std::find(nfo_escapes.begin(), nfo_escapes.end(), new_pair); + if (it == nfo_escapes.end()) { + nfo_escapes.push_back(new_pair); + } +} + +void RemoveEscape(const std::string &key) { + auto it = std::remove_if(nfo_escapes.begin(), nfo_escapes.end(), [key](const auto &p) { + return p.first == key; + }); + nfo_escapes.erase(it, nfo_escapes.end()); +} + std::string FindEscape(char action, int byte) { // Look for a custom escape - foreach(const nfe_rpair& p, nfo_escapes.right.equal_range(byte)) - if (p.second[0] == action) - return " \\" + p.second; + auto it = std::find_if(nfo_escapes.begin(), nfo_escapes.end(), [action, byte](const auto &p) { + return p.first[0] == action && p.second == byte; + }); + if (it != nfo_escapes.end()) { + return " \\" + it->first; + } // Look for a built-in escape - foreach(const esc& e, escapes) - if (e.action==ctoi(action) && e.byte==byte) - return ' ' + std::string(e.str); + for (const esc &e : escapes) { + if (e.action==ctoi(action) && e.byte==byte) return ' ' + std::string(e.str); + } return ""; } std::string FindEscape(char action, int byte, uint offset) { // This time, look for a built-in escape first - foreach(const esc& e, escapes) - if (e.action==ctoi(action) && e.byte==byte && e.pos==offset) - return ' ' + std::string(e.str); + for (const esc &e : escapes) { + if (e.action==ctoi(action) && e.byte==byte && e.pos==offset) return ' ' + std::string(e.str); + } // Look for a custom escape - foreach(const nfe_rpair& p, nfo_escapes.right.equal_range(byte)) - if (p.second[0] == action) - return " \\" + p.second; + auto it = std::find_if(nfo_escapes.begin(), nfo_escapes.end(), [action, byte](const auto &p) { + return p.first[0] == action && p.second == byte; + }); + if (it != nfo_escapes.end()) { + return " \\" + it->first; + } return ""; } -int FindEscape(std::string str) { - foreach(esc e, escapes) - if(str == e.str+1) - return e.byte; - nfe_left_iter ret = nfo_escapes.left.find(str); - if(ret == nfo_escapes.left.end()) - return -1; - return ret->second; +int FindEscape(const std::string &str) { + for (const esc &e : escapes) { + if(str == e.str+1) return e.byte; + } + + const auto &it = std::find_if(nfo_escapes.begin(), nfo_escapes.end(), [str](const auto &p) { + return p.first == str; + }); + if (it != nfo_escapes.end()) { + return it->second; + } + + return -1; } diff --git a/src/mapescapes.h b/src/mapescapes.h index f5a36cd7..d8e6e9c5 100644 --- a/src/mapescapes.h +++ b/src/mapescapes.h @@ -1,6 +1,6 @@ /* * mapescapes.h - * Helper definitions for using boost::bimap + * Helper definitions for using NFO escapes * * Copyright 2009 by Dale McCoy. * @@ -19,25 +19,17 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -/* If your compiler errors on the following lines, boost is not - * properly installed, or your version of boost is too old. - * Get boost from http://www.boost.org */ -#include -#include -#include +#include -using namespace boost::bimaps; - -#define foreach BOOST_FOREACH - -typedef unsigned char U8; +#include "typesize.h" #include "escapes.h" -typedef bimap > nfe_map; -typedef nfe_map::value_type nfe_pair; -typedef nfe_map::left_value_type nfe_lpair; -typedef nfe_map::right_value_type nfe_rpair; -typedef nfe_map::left_iterator nfe_left_iter; -typedef nfe_map::right_iterator nfe_right_iter; +using nfe_map = std::vector>; + +void InsertEscape(const std::string &key, int val); +void RemoveEscape(const std::string &key); +std::string FindEscape(char action, int byte); +std::string FindEscape(char action, int byte, uint offset); +int FindEscape(const std::string &str); extern nfe_map nfo_escapes; diff --git a/src/nforenum.cpp b/src/nforenum.cpp index 0e13bd29..0776e8d3 100644 --- a/src/nforenum.cpp +++ b/src/nforenum.cpp @@ -65,8 +65,6 @@ #include "mapescapes.h" #include "data.h" -nfe_map nfo_escapes; - #ifndef _MSC_VER //Cygwin's GCC #defines __cdecl, but other GCCs do not //#undef it to prevent GCC from warning on the #define, @@ -348,7 +346,9 @@ int process_file(std::istream&in){ if (str == "=") byte--; else if (str[0] == '@') byte = strtol(str.c_str()+1,NULL,16); - else nfo_escapes.insert(nfe_pair(str, byte++)); + else { + InsertEscape(str, byte++); + } } else if (strncmp(sprite.c_str(), "// ",3)) { // EEEP! No "Format:" line in this file! IssueMessage(0, APPARENTLY_NOT_NFO); SetCode(EPARSE); @@ -360,8 +360,9 @@ int process_file(std::istream&in){ // Now remove all defaults. This serves two purposes: // 1) Prevent incorrectly specified defaults from causing problems later. // 2) Allow the beautifier to select custom escapes over built-ins. - foreach(const esc& e, escapes) - nfo_escapes.left.erase(e.str+1); + for (const esc& e : escapes) { + RemoveEscape(e.str + 1); + } } }else{ IssueMessage(0,UNKNOWN_VERSION,1); @@ -477,25 +478,27 @@ int process_file(std::istream&in){ (*real_out)< 6) { // (re)insert default escapes - foreach(const esc& e, escapes) - nfo_escapes.insert(nfe_pair(e.str+1, e.byte)); + for (const esc &e : escapes) { + InsertEscape(e.str + 1, e.byte); + } (*real_out)<<"// Escapes:"; int oldbyte = -1; for (int act = 0; act < 255; act++) { - foreach (const nfe_rpair& p, nfo_escapes.right) { - if (p.second[0] != act) continue; + for (const auto &p : nfo_escapes) { + if (p.first[0] != act) continue; - if (p.first == oldbyte) { + if (p.second == oldbyte) { (*real_out)<<" ="; --oldbyte; - } else if (p.first < oldbyte) { + } else if (p.second < oldbyte) { (*real_out)<<"\n// Escapes:"; oldbyte = -1; } - while (++oldbyte != p.first) - (*real_out)<<" "<second; - (*real_out)<<" "< - /* file handling defs: * dirname contains the name of the sprites directory * foo_ext contains the extention to use for foo @@ -46,32 +41,30 @@ typedef unsigned short ushort; typedef unsigned char uchar; #if defined DEBUG || defined _DEBUG -inline int _FORCE_INT_(int x){return x;} #define verify assert #else #define verify(x) (void(x)) -#define _FORCE_INT_(x) ((int)x) #endif +#include + enum{EOK,EWARN=3,EERROR,EPARSE,EFILE,EDATA,EFATAL}; void SetCode(int); -#define INTERNAL_ERROR(var,val)\ - if(true){\ - IssueMessage(0,INTERNAL_ERROR_TEXT,__FILE__,__LINE__,_spritenum,#var,_FORCE_INT_(val),BOOST_CURRENT_FUNCTION);\ - assert(false);\ - exit(EFATAL);\ - }else\ - ((void)0) +#define INTERNAL_ERROR(var, val) \ + do { \ + const std::source_location location = std::source_location::current(); \ + IssueMessage(0, INTERNAL_ERROR_TEXT, location.file_name(), location.line(), _spritenum, #var, val, location.function_name()); \ + assert(false); \ + exit(EFATAL); \ + } while (false) #define DEFAULT(var)\ default:\ - INTERNAL_ERROR(var,var); + INTERNAL_ERROR(#var,var); #define VERIFY(cond,var)\ - if(!(cond))INTERNAL_ERROR(var,var);\ - else\ - ((void)0) + if(!(cond)) { INTERNAL_ERROR(#var,var); } #define EXPECTED_BYTES(off) (off>>24) #define EXPECTED_LOC(off) (off&0xFFFFFF) diff --git a/src/pseudo.cpp b/src/pseudo.cpp index d81fa505..c260e620 100644 --- a/src/pseudo.cpp +++ b/src/pseudo.cpp @@ -19,25 +19,16 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include #include #include #include +#include #include #include -/* If your compiler errors on the following lines, boost is not - * properly installed. - * Get boost from http://www.boost.org */ -#include -#include -#include -#include -#include - -using namespace boost::gregorian; -#define foreach BOOST_FOREACH - #include"nforenum.h" +#include"mapescapes.h" #include"pseudo.h" #include"globals.h" #include"messages.h" @@ -53,6 +44,53 @@ bool TrySetVersion(int); //QEXT: \Uxxxx, usually. enum{HEX,TEXT,UTF8,ENDQUOTE,QESC,QEXT,NQEXT,NOBREAK=0x80}; +using namespace std::chrono; + +constexpr year_month_day SINCE_1920{year(1920), month(1), day(1)}; + +uint PseudoSprite::Byte::val() const { + return this->p->ExtractByte(this->read_len(this->offs)); +} + +uint PseudoSprite::Word::val() const { + return this->p->ExtractWord(this->read_len(this->offs)); +} + +uint PseudoSprite::ExtByte::val() const { + return this->p->ExtractExtended(this->read_len(this->offs)); +} + +uint PseudoSprite::Dword::val() const { + return this->p->ExtractDword(this->read_len(this->offs)); +} + +uint PseudoSprite::BaseSeqAccess::loc() const { + return offs; +} + +PseudoSprite::Byte& PseudoSprite::Byte::set(uint u) { + p->SetByteAt(offs, u); + return *this; +} + +PseudoSprite::Word& PseudoSprite::Word::set(uint u) { + p->SetByteAt(offs, u&0xFF); + p->SetByteAt(offs, u>>8); + return *this; +} + +PseudoSprite& PseudoSprite::operator >>(PseudoSprite::BaseSeqAccess &b) { + b.p = this; + b.offs = extract_offs; + extract_offs += b.read_len(extract_offs); + return *this; +} + +PseudoSprite& PseudoSprite::Extract(PseudoSprite::BaseSeqAccess &b, uint off) { + b.p = this; + b.offs = off; + return *this; +} #define cur_pos() ((uint)out.str().length()-1) #define next_pos() ((uint)out.str().length()) @@ -64,10 +102,6 @@ enum{HEX,TEXT,UTF8,ENDQUOTE,QESC,QEXT,NQEXT,NOBREAK=0x80}; white="";\ }else ((void)0) -int FindEscape(std::string str); -std::string FindEscape(char, int); -std::string FindEscape(char, int, uint); - PseudoSprite::PseudoSprite(const std::string&sprite,int oldspritenum): orig(sprite), valid(true), @@ -314,9 +348,9 @@ PseudoSprite&PseudoSprite::SetDate(uint i, uint num) { case 1: return SetEscape(i, false, mysprintf(" \\b%d", 1920+ExtractByte(i)), 1); case 2:{ - date::ymd_type ymd = (date(1920,1,1) + days(ExtractWord(i))).year_month_day(); - ushort y = ymd.year, m = ymd.month, d = ymd.day; - return SetEscape(i, false, mysprintf(" \\w%d/%d/%d", y, m, d), 2); + auto ymd = year_month_day(static_cast(SINCE_1920) + static_cast(ExtractWord(i))); + std::string formatted_date = mysprintf(" \\w%d/%u/%u", static_cast(ymd.year()), static_cast(ymd.month()), static_cast(ymd.day())); + return SetEscape(i, false, formatted_date, 2); } case 4: { const int min = 511340, // == PseudoSprite("\\d1400-1-1", 0).ExtractDword(0) max = 3652424, // == PseudoSprite("\\d9999-12-31", 0).ExtractDword(0) @@ -331,9 +365,9 @@ PseudoSprite&PseudoSprite::SetDate(uint i, uint num) { val -= 365*400 + 97; yearmod += 400; } - date::ymd_type ymd = (date(1920,1,1) + days(val-base)).year_month_day(); - uint y = ymd.year+yearmod, m = ymd.month, d = ymd.day; - return SetEscape(i, false, mysprintf(" \\d%d/%d/%d", y, m, d), 4); + auto ymd = year_month_day(static_cast(SINCE_1920) + static_cast(val - base)); + std::string formatted_date = mysprintf(" \\d%d/%u/%u", static_cast(ymd.year()) + yearmod, static_cast(ymd.month()), static_cast(ymd.day())); + return SetEscape(i, false, formatted_date, 4); }} return SetDec(i, num); } @@ -711,8 +745,9 @@ std::ostream&PseudoSprite::output(std::ostream&out){ if(buffer.find('\t')!=NPOS){ // Split into columns std::vector > sections; - foreach(const std::string &line, (Tokenize(buffer, '\n'))) + for (const std::string &line : Tokenize(buffer, '\n')) { sections.push_back(Tokenize(line, '\t')); + } // Count the columns uint columns = (uint)std::ranges::max_element(sections, {}, &std::vector::size)->size(); @@ -721,16 +756,23 @@ std::ostream&PseudoSprite::output(std::ostream&out){ for(uint i=0;i §ion, sections) + for (const std::vector §ion : sections) { if(section.size()>i+1) padWidth = std::max(padWidth, section[i].length()+1); + } // and make it that wide. - foreach(std::vector §ion, sections) + for (std::vector §ion : sections) { if(section.size()>i+1) section[i] += std::string(padWidth - section[i].length(), ' '); + } + } // Tabs are expanded, write each line - foreach(const std::vector&line, sections) - for_each(line.begin(),line.end(),out<&line : sections) { + for (const auto &str : line) { + out << str; + } + out << '\n'; + } }else out<31 && y<100) y+=1900; } else if (w == _D_) { // dword date - extra = 701265; + extra = 1920 * 365; if (d >= 32) std::swap(y, d); // Try DMY instead - // Boost doesn't support years out of the range 1400..9999 - while (y>9999) { - y -= 400; - extra += 365*400 + 97; // 97 leap years every 400 years. - } - while (y<1400) { - y += 400; - extra -= 365*400 + 97; - } } else goto fail; // I can't read a date of that width. - try { - return (date((ushort)y, (ushort)m, (ushort)d) - date(1920, 1, 1)).days() + extra; - } catch (std::out_of_range&) { - // Fall through to fail - } + auto ymd = year_month_day(static_cast(y), static_cast(m), static_cast(d)); + if (!ymd.ok()) goto fail; + int day_count = (static_cast(ymd) - static_cast(SINCE_1920)).count(); + return static_cast(day_count + extra); } fail: // Nothing worked in.clear(std::ios::badbit); return (uint)-1; } + +uint PseudoSprite::BytesRemaining() const { + return (uint)packed.length() - extract_offs; +} + +PseudoSprite& PseudoSprite::seek(uint off) { + extract_offs = off; + return *this; +} diff --git a/src/pseudo.h b/src/pseudo.h index 610dd90a..00dc5cbd 100644 --- a/src/pseudo.h +++ b/src/pseudo.h @@ -25,7 +25,6 @@ #include #include"ExpandingArray.h" - class PseudoSprite{ public: //PseudoSprite(); @@ -134,30 +133,54 @@ class PseudoSprite{ // Support for sequential access public: -#define PS_LOC_REF(size) \ - class size; \ - PseudoSprite& operator >>(size&); \ - PseudoSprite& Extract(size&, uint); \ - class size { \ - public: \ - size(); \ - size& set(uint); \ - uint val() const; \ - uint loc() const; \ - operator uint() const {return val();} \ - friend PseudoSprite& PseudoSprite::operator >>(size&); \ - friend PseudoSprite& PseudoSprite::Extract(size&, uint); \ - private: \ - PseudoSprite *p; \ - uint offs; \ - }; \ - - PS_LOC_REF(Byte) - PS_LOC_REF(Word) - PS_LOC_REF(ExtByte) - PS_LOC_REF(Dword) - -#undef PS_LOC_REF + class BaseSeqAccess; + PseudoSprite &operator>>(PseudoSprite::BaseSeqAccess &); + PseudoSprite &Extract(PseudoSprite::BaseSeqAccess &, uint); + class BaseSeqAccess { + public: + BaseSeqAccess() = default; + virtual uint val() const = 0; + uint loc() const; + operator uint() const { + return this->val(); + } + friend PseudoSprite &PseudoSprite::operator>>(PseudoSprite::BaseSeqAccess &); + friend PseudoSprite &PseudoSprite::Extract(PseudoSprite::BaseSeqAccess &, uint); + protected: + virtual uint read_len(uint) const = 0; + PseudoSprite *p; + uint offs; + }; + + class Byte : public BaseSeqAccess { + public: + uint val() const override; + Byte &set(uint u); + private: + uint read_len(uint) const override { return 1; }; + }; + + class Word : public BaseSeqAccess { + public: + uint val() const override; + Word &set(uint u); + private: + uint read_len(uint) const override { return 2; }; + }; + + class ExtByte : public BaseSeqAccess { + public: + uint val() const override; + private: + uint read_len(uint off) const override { return this->p->ExtendedLen(off); }; + }; + + class Dword : public BaseSeqAccess { + public: + uint val() const override; + private: + uint read_len(uint) const override { return 4; }; + }; uint BytesRemaining() const; PseudoSprite& seek(uint); diff --git a/src/pseudo_seq.cpp b/src/pseudo_seq.cpp deleted file mode 100644 index 8b4612f3..00000000 --- a/src/pseudo_seq.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* - * pseudo_seq.cpp - * Sequential access implementation for the PseudoSprite classes. - * Separated due to preprocessor magic. - * - * Copyright 2009 by Dale McCoy. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef INCLUDING - -#include - -#include "nforenum.h" -#include "pseudo.h" - -#define INCLUDING -#define FOR_CLASS Byte -#define WIDTH(x) 1 -#include "pseudo_seq.cpp" - -#define FOR_CLASS ExtByte -#define EXTRACT Extended -#define WIDTH(x) ExtendedLen(x) -#include "pseudo_seq.cpp" - -#define FOR_CLASS Word -#define WIDTH(x) 2 -#include "pseudo_seq.cpp" - -#define FOR_CLASS Dword -#define WIDTH(x) 4 -#include "pseudo_seq.cpp" - -#undef INCLUDING - -uint PseudoSprite::BytesRemaining() const { - return (uint)packed.length() - extract_offs; -} - -PseudoSprite& PseudoSprite::seek(uint off) { - extract_offs = off; - return *this; -} - -PseudoSprite::Byte& PseudoSprite::Byte::set(uint u) { - p->SetByteAt(offs, u); - return *this; -} - -PseudoSprite::Word& PseudoSprite::Word::set(uint u) { - p->SetByteAt(offs, u&0xFF); - p->SetByteAt(offs, u>>8); - return *this; -} - -#else // INCLUDING - -#ifndef EXTRACT -# define EXTRACT FOR_CLASS -#endif - -PseudoSprite::FOR_CLASS::FOR_CLASS() : - p(NULL) -{} - - -uint PseudoSprite::FOR_CLASS::val() const { - return p->BOOST_PP_CAT(Extract, EXTRACT(offs)); -} - -uint PseudoSprite::FOR_CLASS::loc() const { - return offs; -} - -PseudoSprite& PseudoSprite::operator >>(PseudoSprite::FOR_CLASS& b) { - b.p = this; - b.offs = extract_offs; - extract_offs += WIDTH(extract_offs); - return *this; -} - -PseudoSprite& PseudoSprite::Extract(PseudoSprite::FOR_CLASS& b, uint off) { - b.p = this; - b.offs = off; - return *this; -} - -#undef FOR_CLASS -#undef EXTRACT -#undef WIDTH - - -#endif //INCLUDING diff --git a/src/readinfo.cpp b/src/readinfo.cpp index 8f3d526d..49cc35ef 100644 --- a/src/readinfo.cpp +++ b/src/readinfo.cpp @@ -33,6 +33,7 @@ Version 6: Add binary includes Version 7: Add backslash escapes */ +#include #include #include #include @@ -42,15 +43,13 @@ Version 7: Add backslash escapes #include #include - -// grfcodec requires boost::date_time for its processing of the \wYMD and -// \wDMY formats. Get boost from www.boost.org -#include -using namespace boost::gregorian; - +#include"mapescapes.h" #include"nfosprite.h" #include"inlines.h" +using namespace std::chrono; +constexpr year_month_day SINCE_1920{year(1920), month(1), day(1)}; + extern int _quiet; const char *zoom_levels[ZOOM_LEVELS] = { "normal", "zi4", "zi2", "zo2", "zo4", "zo8" }; const char *depths[DEPTHS] = { "8bpp", "32bpp", "mask" }; @@ -285,8 +284,6 @@ std::string GetUtf8Encode(uint ch){ #undef CHAR -int FindEscape(std::string); - Pseudo::Pseudo(size_t num,int infover,int grfcontversion,const std::string&sprite,int claimed_size){ std::istringstream in(sprite); std::ostringstream out; @@ -456,22 +453,11 @@ uint Pseudo::ReadValue(std::istream& in, width w) // dword date extra = 701265; if (d >= 32) std::swap(y, d); // Try DMY instead - // Boost doesn't support years out of the range 1400..9999 - while (y>9999) { - y -= 400; - extra += 365*400 + 97; // 97 leap years every 400 years. - } - while (y<1400) { - y += 400; - extra -= 365*400 + 97; - } } else goto fail; // I can't read a date of that width. - try { - return (date((ushort)y, (ushort)m, (ushort)d) - date(1920, 1, 1)).days() + extra; - } catch (std::out_of_range&) { - // Fall through to fail - } + return uint(static_cast(year_month_day(static_cast(y), static_cast(m), static_cast(d))) + - static_cast(SINCE_1920) + + static_cast(extra)); } fail: