Updated libopenmpt to version 0.5.2
This commit is contained in:
parent
640e8b7304
commit
dab78ed74f
327 changed files with 23363 additions and 15401 deletions
|
@ -1,4 +1,4 @@
|
||||||
Copyright (c) 2004-2019, OpenMPT contributors
|
Copyright (c) 2004-2020, OpenMPT contributors
|
||||||
Copyright (c) 1997-2003, Olivier Lapicque
|
Copyright (c) 1997-2003, Olivier Lapicque
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@
|
||||||
# ONLY_TEST=0 Only build the test suite.
|
# ONLY_TEST=0 Only build the test suite.
|
||||||
# STRICT=0 Treat warnings as errors.
|
# STRICT=0 Treat warnings as errors.
|
||||||
# MODERN=0 Pass more modern compiler options.
|
# MODERN=0 Pass more modern compiler options.
|
||||||
# STDCXX=c++11 C++ standard version (only for GCC and clang)
|
# STDCXX=c++14 C++ standard version (only for GCC and clang)
|
||||||
# CHECKED=0 Enable run-time assertions.
|
# CHECKED=0 Enable run-time assertions.
|
||||||
# CHECKED_ADDRESS=0 Enable address sanitizer
|
# CHECKED_ADDRESS=0 Enable address sanitizer
|
||||||
# CHECKED_UNDEFINED=0 Enable undefined behaviour sanitizer
|
# CHECKED_UNDEFINED=0 Enable undefined behaviour sanitizer
|
||||||
|
@ -69,6 +69,11 @@
|
||||||
# NO_VORBIS=1 Avoid using libvorbis, even if found
|
# NO_VORBIS=1 Avoid using libvorbis, even if found
|
||||||
# NO_VORBISFILE=1 Avoid using libvorbisfile, even if found
|
# NO_VORBISFILE=1 Avoid using libvorbisfile, even if found
|
||||||
#
|
#
|
||||||
|
# LOCAL_ZLIB=1 Build local copy of zlib, even if found
|
||||||
|
# LOCAL_MPG123=1 Build local copy of libmpg123, even if found
|
||||||
|
# LOCAL_OGG=1 Build local copy of libogg, even if found
|
||||||
|
# LOCAL_VORBIS=1 Build local copy of libvorbis, even if found
|
||||||
|
#
|
||||||
# NO_MINIMP3=1 Do not fallback to minimp3
|
# NO_MINIMP3=1 Do not fallback to minimp3
|
||||||
# NO_STBVORBIS=1 Do not fallback to stb_vorbis
|
# NO_STBVORBIS=1 Do not fallback to stb_vorbis
|
||||||
#
|
#
|
||||||
|
@ -86,7 +91,6 @@
|
||||||
# (defaults are 0):
|
# (defaults are 0):
|
||||||
#
|
#
|
||||||
# NO_PULSEAUDIO=1 Avoid using PulseAudio, even if found
|
# NO_PULSEAUDIO=1 Avoid using PulseAudio, even if found
|
||||||
# NO_SDL=1 Avoid using SDL, even if found
|
|
||||||
# NO_SDL2=1 Avoid using SDL2, even if found
|
# NO_SDL2=1 Avoid using SDL2, even if found
|
||||||
# NO_FLAC=1 Avoid using FLAC, even if found
|
# NO_FLAC=1 Avoid using FLAC, even if found
|
||||||
# NO_SNDFILE=1 Avoid using libsndfile, even if found
|
# NO_SNDFILE=1 Avoid using libsndfile, even if found
|
||||||
|
@ -158,6 +162,7 @@ TEST=1
|
||||||
ONLY_TEST=0
|
ONLY_TEST=0
|
||||||
SOSUFFIX=.so
|
SOSUFFIX=.so
|
||||||
SOSUFFIXWINDOWS=0
|
SOSUFFIXWINDOWS=0
|
||||||
|
NO_SHARED_LINKER_FLAG=0
|
||||||
OPENMPT123=1
|
OPENMPT123=1
|
||||||
MODERN=0
|
MODERN=0
|
||||||
STRICT=0
|
STRICT=0
|
||||||
|
@ -290,7 +295,7 @@ INSTALL_LIB = $(INSTALL) -m 0644
|
||||||
INSTALL_DATA_DIR = $(INSTALL_DIR)
|
INSTALL_DATA_DIR = $(INSTALL_DIR)
|
||||||
INSTALL_MAKE_DIR += -m 0755
|
INSTALL_MAKE_DIR += -m 0755
|
||||||
|
|
||||||
CPPFLAGS += -Icommon -I. -Iinclude/modplug/include -Iinclude
|
CPPFLAGS += -Icommon -I. -Iinclude
|
||||||
|
|
||||||
ifeq ($(MPT_COMPILER_GENERIC),1)
|
ifeq ($(MPT_COMPILER_GENERIC),1)
|
||||||
|
|
||||||
|
@ -407,6 +412,30 @@ ifeq ($(HACK_ARCHIVE_SUPPORT),1)
|
||||||
NO_ZLIB:=1
|
NO_ZLIB:=1
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(LOCAL_ZLIB),1)
|
||||||
|
CPPFLAGS_ZLIB := -DMPT_WITH_ZLIB
|
||||||
|
LDFLAGS_ZLIB :=
|
||||||
|
LDLIBS_ZLIB :=
|
||||||
|
CPPFLAGS_ZLIB += -Iinclude/zlib/
|
||||||
|
LOCAL_ZLIB_SOURCES :=
|
||||||
|
LOCAL_ZLIB_SOURCES += include/zlib/adler32.c
|
||||||
|
LOCAL_ZLIB_SOURCES += include/zlib/compress.c
|
||||||
|
LOCAL_ZLIB_SOURCES += include/zlib/crc32.c
|
||||||
|
LOCAL_ZLIB_SOURCES += include/zlib/deflate.c
|
||||||
|
LOCAL_ZLIB_SOURCES += include/zlib/gzclose.c
|
||||||
|
LOCAL_ZLIB_SOURCES += include/zlib/gzlib.c
|
||||||
|
LOCAL_ZLIB_SOURCES += include/zlib/gzread.c
|
||||||
|
LOCAL_ZLIB_SOURCES += include/zlib/gzwrite.c
|
||||||
|
LOCAL_ZLIB_SOURCES += include/zlib/infback.c
|
||||||
|
LOCAL_ZLIB_SOURCES += include/zlib/inffast.c
|
||||||
|
LOCAL_ZLIB_SOURCES += include/zlib/inflate.c
|
||||||
|
LOCAL_ZLIB_SOURCES += include/zlib/inftrees.c
|
||||||
|
LOCAL_ZLIB_SOURCES += include/zlib/trees.c
|
||||||
|
LOCAL_ZLIB_SOURCES += include/zlib/uncompr.c
|
||||||
|
LOCAL_ZLIB_SOURCES += include/zlib/zutil.c
|
||||||
|
include/zlib/%.o : CFLAGS+=$(CFLAGS_SILENT) -DSTDC -DZ_HAVE_UNISTD_H
|
||||||
|
include/zlib/%.test.o : CFLAGS+=$(CFLAGS_SILENT) -DSTDC -DZ_HAVE_UNISTD_H
|
||||||
|
else
|
||||||
ifeq ($(NO_ZLIB),1)
|
ifeq ($(NO_ZLIB),1)
|
||||||
else
|
else
|
||||||
#LDLIBS += -lz
|
#LDLIBS += -lz
|
||||||
|
@ -424,7 +453,44 @@ endif
|
||||||
NO_ZLIB:=1
|
NO_ZLIB:=1
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(LOCAL_MPG123),1)
|
||||||
|
CPPFLAGS_MPG123 := -DMPT_WITH_MPG123
|
||||||
|
LDFLAGS_MPG123 :=
|
||||||
|
LDLIBS_MPG123 :=
|
||||||
|
CPPFLAGS_MPG123 += -Iinclude/mpg123/src/libmpg123/ -Iinclude/mpg123/src/compat/ -Iinclude/mpg123/src/ -Iinclude/mpg123/ports/makefile/
|
||||||
|
LOCAL_MPG123_SOURCES :=
|
||||||
|
LOCAL_MPG123_SOURCES += include/mpg123/src/compat/compat.c
|
||||||
|
LOCAL_MPG123_SOURCES += include/mpg123/src/compat/compat_str.c
|
||||||
|
LOCAL_MPG123_SOURCES += include/mpg123/src/libmpg123/dct64.c
|
||||||
|
LOCAL_MPG123_SOURCES += include/mpg123/src/libmpg123/equalizer.c
|
||||||
|
LOCAL_MPG123_SOURCES += include/mpg123/src/libmpg123/feature.c
|
||||||
|
LOCAL_MPG123_SOURCES += include/mpg123/src/libmpg123/format.c
|
||||||
|
LOCAL_MPG123_SOURCES += include/mpg123/src/libmpg123/frame.c
|
||||||
|
LOCAL_MPG123_SOURCES += include/mpg123/src/libmpg123/icy.c
|
||||||
|
LOCAL_MPG123_SOURCES += include/mpg123/src/libmpg123/icy2utf8.c
|
||||||
|
LOCAL_MPG123_SOURCES += include/mpg123/src/libmpg123/id3.c
|
||||||
|
LOCAL_MPG123_SOURCES += include/mpg123/src/libmpg123/index.c
|
||||||
|
LOCAL_MPG123_SOURCES += include/mpg123/src/libmpg123/layer1.c
|
||||||
|
LOCAL_MPG123_SOURCES += include/mpg123/src/libmpg123/layer2.c
|
||||||
|
LOCAL_MPG123_SOURCES += include/mpg123/src/libmpg123/layer3.c
|
||||||
|
LOCAL_MPG123_SOURCES += include/mpg123/src/libmpg123/libmpg123.c
|
||||||
|
LOCAL_MPG123_SOURCES += include/mpg123/src/libmpg123/ntom.c
|
||||||
|
LOCAL_MPG123_SOURCES += include/mpg123/src/libmpg123/optimize.c
|
||||||
|
LOCAL_MPG123_SOURCES += include/mpg123/src/libmpg123/parse.c
|
||||||
|
LOCAL_MPG123_SOURCES += include/mpg123/src/libmpg123/readers.c
|
||||||
|
LOCAL_MPG123_SOURCES += include/mpg123/src/libmpg123/stringbuf.c
|
||||||
|
LOCAL_MPG123_SOURCES += include/mpg123/src/libmpg123/synth.c
|
||||||
|
LOCAL_MPG123_SOURCES += include/mpg123/src/libmpg123/synth_8bit.c
|
||||||
|
LOCAL_MPG123_SOURCES += include/mpg123/src/libmpg123/synth_real.c
|
||||||
|
LOCAL_MPG123_SOURCES += include/mpg123/src/libmpg123/synth_s32.c
|
||||||
|
LOCAL_MPG123_SOURCES += include/mpg123/src/libmpg123/tabinit.c
|
||||||
|
include/mpg123/src/compat/%.o : CFLAGS+=$(CFLAGS_SILENT) -DOPT_GENERIC
|
||||||
|
include/mpg123/src/compat/%.test.o : CFLAGS+=$(CFLAGS_SILENT) -DOPT_GENERIC
|
||||||
|
include/mpg123/src/libmpg123/%.o : CFLAGS+=$(CFLAGS_SILENT) -DOPT_GENERIC
|
||||||
|
include/mpg123/src/libmpg123/%.test.o : CFLAGS+=$(CFLAGS_SILENT) -DOPT_GENERIC
|
||||||
|
else
|
||||||
ifeq ($(NO_MPG123),1)
|
ifeq ($(NO_MPG123),1)
|
||||||
else
|
else
|
||||||
#LDLIBS += -lmpg123
|
#LDLIBS += -lmpg123
|
||||||
|
@ -442,7 +508,19 @@ endif
|
||||||
NO_MPG123:=1
|
NO_MPG123:=1
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(LOCAL_OGG),1)
|
||||||
|
CPPFLAGS_OGG := -DMPT_WITH_OGG
|
||||||
|
LDFLAGS_OGG :=
|
||||||
|
LDLIBS_OGG :=
|
||||||
|
CPPFLAGS_OGG += -Iinclude/ogg/include/ -Iinclude/ogg/ports/makefile/
|
||||||
|
LOCAL_OGG_SOURCES :=
|
||||||
|
LOCAL_OGG_SOURCES += include/ogg/src/bitwise.c
|
||||||
|
LOCAL_OGG_SOURCES += include/ogg/src/framing.c
|
||||||
|
include/ogg/src/%.o : CFLAGS+=$(CFLAGS_SILENT)
|
||||||
|
include/ogg/src/%.test.o : CFLAGS+=$(CFLAGS_SILENT)
|
||||||
|
else
|
||||||
ifeq ($(NO_OGG),1)
|
ifeq ($(NO_OGG),1)
|
||||||
else
|
else
|
||||||
#LDLIBS += -logg
|
#LDLIBS += -logg
|
||||||
|
@ -460,7 +538,39 @@ endif
|
||||||
NO_OGG:=1
|
NO_OGG:=1
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(LOCAL_VORBIS),1)
|
||||||
|
CPPFLAGS_VORBIS := -DMPT_WITH_VORBIS
|
||||||
|
LDFLAGS_VORBIS :=
|
||||||
|
LDLIBS_VORBIS :=
|
||||||
|
CPPFLAGS_VORBIS += -Iinclude/vorbis/include/ -Iinclude/vorbis/lib/ -DHAVE_ALLOCA_H
|
||||||
|
LOCAL_VORBIS_SOURCES :=
|
||||||
|
LOCAL_VORBIS_SOURCES += include/vorbis/lib/analysis.c
|
||||||
|
LOCAL_VORBIS_SOURCES += include/vorbis/lib/bitrate.c
|
||||||
|
LOCAL_VORBIS_SOURCES += include/vorbis/lib/block.c
|
||||||
|
LOCAL_VORBIS_SOURCES += include/vorbis/lib/codebook.c
|
||||||
|
LOCAL_VORBIS_SOURCES += include/vorbis/lib/envelope.c
|
||||||
|
LOCAL_VORBIS_SOURCES += include/vorbis/lib/floor0.c
|
||||||
|
LOCAL_VORBIS_SOURCES += include/vorbis/lib/floor1.c
|
||||||
|
LOCAL_VORBIS_SOURCES += include/vorbis/lib/info.c
|
||||||
|
LOCAL_VORBIS_SOURCES += include/vorbis/lib/lookup.c
|
||||||
|
LOCAL_VORBIS_SOURCES += include/vorbis/lib/lpc.c
|
||||||
|
LOCAL_VORBIS_SOURCES += include/vorbis/lib/lsp.c
|
||||||
|
LOCAL_VORBIS_SOURCES += include/vorbis/lib/mapping0.c
|
||||||
|
LOCAL_VORBIS_SOURCES += include/vorbis/lib/mdct.c
|
||||||
|
LOCAL_VORBIS_SOURCES += include/vorbis/lib/psy.c
|
||||||
|
LOCAL_VORBIS_SOURCES += include/vorbis/lib/registry.c
|
||||||
|
LOCAL_VORBIS_SOURCES += include/vorbis/lib/res0.c
|
||||||
|
LOCAL_VORBIS_SOURCES += include/vorbis/lib/sharedbook.c
|
||||||
|
LOCAL_VORBIS_SOURCES += include/vorbis/lib/smallft.c
|
||||||
|
LOCAL_VORBIS_SOURCES += include/vorbis/lib/synthesis.c
|
||||||
|
LOCAL_VORBIS_SOURCES += include/vorbis/lib/vorbisenc.c
|
||||||
|
LOCAL_VORBIS_SOURCES += include/vorbis/lib/vorbisfile.c
|
||||||
|
LOCAL_VORBIS_SOURCES += include/vorbis/lib/window.c
|
||||||
|
include/vorbis/lib/%.o : CFLAGS+=$(CFLAGS_SILENT)
|
||||||
|
include/vorbis/lib/%.test.o : CFLAGS+=$(CFLAGS_SILENT)
|
||||||
|
else
|
||||||
ifeq ($(NO_VORBIS),1)
|
ifeq ($(NO_VORBIS),1)
|
||||||
else
|
else
|
||||||
#LDLIBS += -lvorbis
|
#LDLIBS += -lvorbis
|
||||||
|
@ -478,7 +588,13 @@ endif
|
||||||
NO_VORBIS:=1
|
NO_VORBIS:=1
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(LOCAL_VORBIS),1)
|
||||||
|
CPPFLAGS_VORBISFILE := -DMPT_WITH_VORBISFILE
|
||||||
|
LDFLAGS_VORBISFILE :=
|
||||||
|
LDLIBS_VORBISFILE :=
|
||||||
|
else
|
||||||
ifeq ($(NO_VORBISFILE),1)
|
ifeq ($(NO_VORBISFILE),1)
|
||||||
else
|
else
|
||||||
#LDLIBS += -lvorbisfile
|
#LDLIBS += -lvorbisfile
|
||||||
|
@ -496,15 +612,15 @@ endif
|
||||||
NO_VORBISFILE:=1
|
NO_VORBISFILE:=1
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(NO_SDL2),1)
|
ifeq ($(NO_SDL2),1)
|
||||||
else
|
else
|
||||||
#LDLIBS += -lsdl2
|
#LDLIBS += -lsdl2
|
||||||
ifeq ($(shell pkg-config$(TOOLCHAIN_SUFFIX) --exists sdl2 && echo yes),yes)
|
ifeq ($(shell pkg-config$(TOOLCHAIN_SUFFIX) --exists 'sdl2 >= 2.0.4' && echo yes),yes)
|
||||||
CPPFLAGS_SDL := $(shell pkg-config$(TOOLCHAIN_SUFFIX) --cflags-only-I sdl2 ) -DMPT_WITH_SDL2
|
CPPFLAGS_SDL2 := $(shell pkg-config$(TOOLCHAIN_SUFFIX) --cflags-only-I 'sdl2 >= 2.0.4' ) -DMPT_WITH_SDL2
|
||||||
LDFLAGS_SDL := $(shell pkg-config$(TOOLCHAIN_SUFFIX) --libs-only-L sdl2 ) $(shell pkg-config$(TOOLCHAIN_SUFFIX) --libs-only-other sdl2 )
|
LDFLAGS_SDL2 := $(shell pkg-config$(TOOLCHAIN_SUFFIX) --libs-only-L 'sdl2 >= 2.0.4' ) $(shell pkg-config$(TOOLCHAIN_SUFFIX) --libs-only-other 'sdl2 >= 2.0.4' )
|
||||||
LDLIBS_SDL := $(shell pkg-config$(TOOLCHAIN_SUFFIX) --libs-only-l sdl2 )
|
LDLIBS_SDL2 := $(shell pkg-config$(TOOLCHAIN_SUFFIX) --libs-only-l 'sdl2 >= 2.0.4' )
|
||||||
NO_SDL:=1
|
|
||||||
else
|
else
|
||||||
ifeq ($(FORCE_DEPS),1)
|
ifeq ($(FORCE_DEPS),1)
|
||||||
$(error sdl2 not found)
|
$(error sdl2 not found)
|
||||||
|
@ -515,23 +631,6 @@ NO_SDL2:=1
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(NO_SDL),1)
|
|
||||||
else
|
|
||||||
#LDLIBS += -lsdl
|
|
||||||
ifeq ($(shell pkg-config$(TOOLCHAIN_SUFFIX) --exists sdl && echo yes),yes)
|
|
||||||
CPPFLAGS_SDL := $(shell pkg-config$(TOOLCHAIN_SUFFIX) --cflags-only-I sdl ) -DMPT_WITH_SDL
|
|
||||||
LDFLAGS_SDL := $(shell pkg-config$(TOOLCHAIN_SUFFIX) --libs-only-L sdl ) $(shell pkg-config$(TOOLCHAIN_SUFFIX) --libs-only-other sdl )
|
|
||||||
LDLIBS_SDL := $(shell pkg-config$(TOOLCHAIN_SUFFIX) --libs-only-l sdl )
|
|
||||||
else
|
|
||||||
ifeq ($(FORCE_DEPS),1)
|
|
||||||
$(error sdl not found)
|
|
||||||
else
|
|
||||||
$(warning warning: sdl not found)
|
|
||||||
endif
|
|
||||||
NO_SDL:=1
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(NO_PORTAUDIO),1)
|
ifeq ($(NO_PORTAUDIO),1)
|
||||||
else
|
else
|
||||||
#LDLIBS += -lportaudio
|
#LDLIBS += -lportaudio
|
||||||
|
@ -629,7 +728,7 @@ CPPFLAGS += -DMPT_BUILD_HACK_ARCHIVE_SUPPORT
|
||||||
endif
|
endif
|
||||||
|
|
||||||
CPPCHECK_FLAGS += -j $(NUMTHREADS)
|
CPPCHECK_FLAGS += -j $(NUMTHREADS)
|
||||||
CPPCHECK_FLAGS += --std=c99 --std=c++11
|
CPPCHECK_FLAGS += --std=c99 --std=c++14
|
||||||
CPPCHECK_FLAGS += --quiet
|
CPPCHECK_FLAGS += --quiet
|
||||||
CPPCHECK_FLAGS += --enable=warning --inline-suppr --template='{file}:{line}: warning: {severity}: {message} [{id}]'
|
CPPCHECK_FLAGS += --enable=warning --inline-suppr --template='{file}:{line}: warning: {severity}: {message} [{id}]'
|
||||||
CPPCHECK_FLAGS += --suppress=missingIncludeSystem
|
CPPCHECK_FLAGS += --suppress=missingIncludeSystem
|
||||||
|
@ -639,9 +738,9 @@ CPPFLAGS += $(CPPFLAGS_ZLIB) $(CPPFLAGS_MPG123) $(CPPFLAGS_OGG) $(CPPFLAGS_VORBI
|
||||||
LDFLAGS += $(LDFLAGS_ZLIB) $(LDFLAGS_MPG123) $(LDFLAGS_OGG) $(LDFLAGS_VORBIS) $(LDFLAGS_VORBISFILE)
|
LDFLAGS += $(LDFLAGS_ZLIB) $(LDFLAGS_MPG123) $(LDFLAGS_OGG) $(LDFLAGS_VORBIS) $(LDFLAGS_VORBISFILE)
|
||||||
LDLIBS += $(LDLIBS_ZLIB) $(LDLIBS_MPG123) $(LDLIBS_OGG) $(LDLIBS_VORBIS) $(LDLIBS_VORBISFILE)
|
LDLIBS += $(LDLIBS_ZLIB) $(LDLIBS_MPG123) $(LDLIBS_OGG) $(LDLIBS_VORBIS) $(LDLIBS_VORBISFILE)
|
||||||
|
|
||||||
CPPFLAGS_OPENMPT123 += $(CPPFLAGS_SDL2) $(CPPFLAGS_SDL) $(CPPFLAGS_PORTAUDIO) $(CPPFLAGS_PULSEAUDIO) $(CPPFLAGS_FLAC) $(CPPFLAGS_SNDFILE) $(CPPFLAGS_ALLEGRO42)
|
CPPFLAGS_OPENMPT123 += $(CPPFLAGS_SDL2) $(CPPFLAGS_PORTAUDIO) $(CPPFLAGS_PULSEAUDIO) $(CPPFLAGS_FLAC) $(CPPFLAGS_SNDFILE) $(CPPFLAGS_ALLEGRO42)
|
||||||
LDFLAGS_OPENMPT123 += $(LDFLAGS_SDL2) $(LDFLAGS_SDL) $(LDFLAGS_PORTAUDIO) $(LDFLAGS_PULSEAUDIO) $(LDFLAGS_FLAC) $(LDFLAGS_SNDFILE) $(LDFLAGS_ALLEGRO42)
|
LDFLAGS_OPENMPT123 += $(LDFLAGS_SDL2) $(LDFLAGS_PORTAUDIO) $(LDFLAGS_PULSEAUDIO) $(LDFLAGS_FLAC) $(LDFLAGS_SNDFILE) $(LDFLAGS_ALLEGRO42)
|
||||||
LDLIBS_OPENMPT123 += $(LDLIBS_SDL2) $(LDLIBS_SDL) $(LDLIBS_PORTAUDIO) $(LDLIBS_PULSEAUDIO) $(LDLIBS_FLAC) $(LDLIBS_SNDFILE) $(LDLIBS_ALLEGRO42)
|
LDLIBS_OPENMPT123 += $(LDLIBS_SDL2) $(LDLIBS_PORTAUDIO) $(LDLIBS_PULSEAUDIO) $(LDLIBS_FLAC) $(LDLIBS_SNDFILE) $(LDLIBS_ALLEGRO42)
|
||||||
|
|
||||||
|
|
||||||
%: %.o
|
%: %.o
|
||||||
|
@ -761,14 +860,23 @@ LIBOPENMPT_CXX_SOURCES += \
|
||||||
|
|
||||||
include/miniz/miniz.o : CFLAGS+=$(CFLAGS_SILENT)
|
include/miniz/miniz.o : CFLAGS+=$(CFLAGS_SILENT)
|
||||||
include/miniz/miniz.test.o : CFLAGS+=$(CFLAGS_SILENT)
|
include/miniz/miniz.test.o : CFLAGS+=$(CFLAGS_SILENT)
|
||||||
|
ifeq ($(LOCAL_ZLIB),1)
|
||||||
|
LIBOPENMPT_C_SOURCES += $(LOCAL_ZLIB_SOURCES)
|
||||||
|
LIBOPENMPTTEST_C_SOURCES += $(LOCAL_ZLIB_SOURCES)
|
||||||
|
else
|
||||||
ifeq ($(NO_ZLIB),1)
|
ifeq ($(NO_ZLIB),1)
|
||||||
LIBOPENMPT_C_SOURCES += include/miniz/miniz.c
|
LIBOPENMPT_C_SOURCES += include/miniz/miniz.c
|
||||||
LIBOPENMPTTEST_C_SOURCES += include/miniz/miniz.c
|
LIBOPENMPTTEST_C_SOURCES += include/miniz/miniz.c
|
||||||
CPPFLAGS += -DMPT_WITH_MINIZ
|
CPPFLAGS += -DMPT_WITH_MINIZ
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
include/minimp3/minimp3.o : CFLAGS+=$(CFLAGS_SILENT)
|
include/minimp3/minimp3.o : CFLAGS+=$(CFLAGS_SILENT)
|
||||||
include/minimp3/minimp3.test.o : CFLAGS+=$(CFLAGS_SILENT)
|
include/minimp3/minimp3.test.o : CFLAGS+=$(CFLAGS_SILENT)
|
||||||
|
ifeq ($(LOCAL_MPG123),1)
|
||||||
|
LIBOPENMPT_C_SOURCES += $(LOCAL_MPG123_SOURCES)
|
||||||
|
LIBOPENMPTTEST_C_SOURCES += $(LOCAL_MPG123_SOURCES)
|
||||||
|
else
|
||||||
ifeq ($(NO_MPG123),1)
|
ifeq ($(NO_MPG123),1)
|
||||||
ifeq ($(NO_MINIMP3),1)
|
ifeq ($(NO_MINIMP3),1)
|
||||||
else
|
else
|
||||||
|
@ -777,9 +885,18 @@ LIBOPENMPTTEST_C_SOURCES += include/minimp3/minimp3.c
|
||||||
CPPFLAGS += -DMPT_WITH_MINIMP3
|
CPPFLAGS += -DMPT_WITH_MINIMP3
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
include/stb_vorbis/stb_vorbis.o : CFLAGS+=$(CFLAGS_SILENT)
|
include/stb_vorbis/stb_vorbis.o : CFLAGS+=$(CFLAGS_SILENT)
|
||||||
include/stb_vorbis/stb_vorbis.test.o : CFLAGS+=$(CFLAGS_SILENT)
|
include/stb_vorbis/stb_vorbis.test.o : CFLAGS+=$(CFLAGS_SILENT)
|
||||||
|
ifeq ($(LOCAL_VORBIS),1)
|
||||||
|
ifeq ($(LOCAL_OGG),1)
|
||||||
|
LIBOPENMPT_C_SOURCES += $(LOCAL_OGG_SOURCES)
|
||||||
|
LIBOPENMPTTEST_C_SOURCES += $(LOCAL_OGG_SOURCES)
|
||||||
|
endif
|
||||||
|
LIBOPENMPT_C_SOURCES += $(LOCAL_VORBIS_SOURCES)
|
||||||
|
LIBOPENMPTTEST_C_SOURCES += $(LOCAL_VORBIS_SOURCES)
|
||||||
|
else
|
||||||
ifeq ($(NO_OGG),1)
|
ifeq ($(NO_OGG),1)
|
||||||
ifeq ($(NO_STBVORBIS),1)
|
ifeq ($(NO_STBVORBIS),1)
|
||||||
else
|
else
|
||||||
|
@ -807,6 +924,7 @@ else
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
LIBOPENMPT_OBJECTS += $(LIBOPENMPT_CXX_SOURCES:.cpp=.o) $(LIBOPENMPT_C_SOURCES:.c=.o)
|
LIBOPENMPT_OBJECTS += $(LIBOPENMPT_CXX_SOURCES:.cpp=.o) $(LIBOPENMPT_C_SOURCES:.c=.o)
|
||||||
LIBOPENMPT_DEPENDS = $(LIBOPENMPT_OBJECTS:.o=.d)
|
LIBOPENMPT_DEPENDS = $(LIBOPENMPT_OBJECTS:.o=.d)
|
||||||
|
@ -820,18 +938,6 @@ OBJECTS_LIBOPENMPT += $(LIBOPENMPT_OBJECTS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
LIBOPENMPT_MODPLUG_C_SOURCES += \
|
|
||||||
libopenmpt/libopenmpt_modplug.c \
|
|
||||||
|
|
||||||
LIBOPENMPT_MODPLUG_CPP_SOURCES += \
|
|
||||||
libopenmpt/libopenmpt_modplug_cpp.cpp \
|
|
||||||
|
|
||||||
LIBOPENMPT_MODPLUG_OBJECTS = $(LIBOPENMPT_MODPLUG_C_SOURCES:.c=.o) $(LIBOPENMPT_MODPLUG_CPP_SOURCES:.cpp=.o)
|
|
||||||
LIBOPENMPT_MODPLUG_DEPENDS = $(LIBOPENMPT_MODPLUG_OBJECTS:.o=.d)
|
|
||||||
ALL_OBJECTS += $(LIBOPENMPT_MODPLUG_OBJECTS)
|
|
||||||
ALL_DEPENDS += $(LIBOPENMPT_MODPLUG_DEPENDS)
|
|
||||||
|
|
||||||
|
|
||||||
OPENMPT123_CXX_SOURCES += \
|
OPENMPT123_CXX_SOURCES += \
|
||||||
$(sort $(wildcard openmpt123/*.cpp)) \
|
$(sort $(wildcard openmpt123/*.cpp)) \
|
||||||
|
|
||||||
|
@ -879,7 +985,6 @@ all:
|
||||||
|
|
||||||
ifeq ($(DYNLINK),1)
|
ifeq ($(DYNLINK),1)
|
||||||
OUTPUTS += bin/libopenmpt$(SOSUFFIX)
|
OUTPUTS += bin/libopenmpt$(SOSUFFIX)
|
||||||
OUTPUTS += bin/libopenmpt_modplug$(SOSUFFIX)
|
|
||||||
endif
|
endif
|
||||||
ifeq ($(SHARED_LIB),1)
|
ifeq ($(SHARED_LIB),1)
|
||||||
OUTPUTS += bin/libopenmpt$(SOSUFFIX)
|
OUTPUTS += bin/libopenmpt$(SOSUFFIX)
|
||||||
|
@ -937,22 +1042,30 @@ MISC_OUTPUTS += libopenmpt$(SOSUFFIX)
|
||||||
MISC_OUTPUTS += bin/.docs
|
MISC_OUTPUTS += bin/.docs
|
||||||
MISC_OUTPUTS += bin/libopenmpt_test$(EXESUFFIX)
|
MISC_OUTPUTS += bin/libopenmpt_test$(EXESUFFIX)
|
||||||
MISC_OUTPUTS += bin/libopenmpt_test.wasm
|
MISC_OUTPUTS += bin/libopenmpt_test.wasm
|
||||||
|
MISC_OUTPUTS += bin/libopenmpt_test.wasm.js
|
||||||
MISC_OUTPUTS += bin/libopenmpt_test.js.mem
|
MISC_OUTPUTS += bin/libopenmpt_test.js.mem
|
||||||
MISC_OUTPUTS += bin/made.docs
|
MISC_OUTPUTS += bin/made.docs
|
||||||
MISC_OUTPUTS += bin/$(LIBOPENMPT_SONAME)
|
MISC_OUTPUTS += bin/$(LIBOPENMPT_SONAME)
|
||||||
MISC_OUTPUTS += bin/libopenmpt.wasm
|
MISC_OUTPUTS += bin/libopenmpt.wasm
|
||||||
|
MISC_OUTPUTS += bin/libopenmpt.wasm.js
|
||||||
MISC_OUTPUTS += bin/libopenmpt.js.mem
|
MISC_OUTPUTS += bin/libopenmpt.js.mem
|
||||||
MISC_OUTPUTS += bin/libopenmpt_example_c.wasm
|
MISC_OUTPUTS += bin/libopenmpt_example_c.wasm
|
||||||
|
MISC_OUTPUTS += bin/libopenmpt_example_c.wasm.js
|
||||||
MISC_OUTPUTS += bin/libopenmpt_example_c.js.mem
|
MISC_OUTPUTS += bin/libopenmpt_example_c.js.mem
|
||||||
MISC_OUTPUTS += bin/libopenmpt_example_c_mem.wasm
|
MISC_OUTPUTS += bin/libopenmpt_example_c_mem.wasm
|
||||||
|
MISC_OUTPUTS += bin/libopenmpt_example_c_mem.wasm.js
|
||||||
MISC_OUTPUTS += bin/libopenmpt_example_c_mem.js.mem
|
MISC_OUTPUTS += bin/libopenmpt_example_c_mem.js.mem
|
||||||
MISC_OUTPUTS += bin/libopenmpt_example_c_pipe.wasm
|
MISC_OUTPUTS += bin/libopenmpt_example_c_pipe.wasm
|
||||||
|
MISC_OUTPUTS += bin/libopenmpt_example_c_pipe.wasm.js
|
||||||
MISC_OUTPUTS += bin/libopenmpt_example_c_pipe.js.mem
|
MISC_OUTPUTS += bin/libopenmpt_example_c_pipe.js.mem
|
||||||
MISC_OUTPUTS += bin/libopenmpt_example_c_probe.wasm
|
MISC_OUTPUTS += bin/libopenmpt_example_c_probe.wasm
|
||||||
|
MISC_OUTPUTS += bin/libopenmpt_example_c_probe.wasm.js
|
||||||
MISC_OUTPUTS += bin/libopenmpt_example_c_probe.js.mem
|
MISC_OUTPUTS += bin/libopenmpt_example_c_probe.js.mem
|
||||||
MISC_OUTPUTS += bin/libopenmpt_example_c_stdout.wasm
|
MISC_OUTPUTS += bin/libopenmpt_example_c_stdout.wasm
|
||||||
|
MISC_OUTPUTS += bin/libopenmpt_example_c_stdout.wasm.js
|
||||||
MISC_OUTPUTS += bin/libopenmpt_example_c_stdout.js.mem
|
MISC_OUTPUTS += bin/libopenmpt_example_c_stdout.js.mem
|
||||||
MISC_OUTPUTS += bin/libopenmpt_example_c_unsafe.wasm
|
MISC_OUTPUTS += bin/libopenmpt_example_c_unsafe.wasm
|
||||||
|
MISC_OUTPUTS += bin/libopenmpt_example_c_unsafe.wasm.js
|
||||||
MISC_OUTPUTS += bin/libopenmpt_example_c_unsafe.js.mem
|
MISC_OUTPUTS += bin/libopenmpt_example_c_unsafe.js.mem
|
||||||
MISC_OUTPUTS += bin/openmpt.a
|
MISC_OUTPUTS += bin/openmpt.a
|
||||||
#old
|
#old
|
||||||
|
@ -1095,24 +1208,6 @@ ifeq ($(MPT_WITH_DOXYGEN),1)
|
||||||
$(INSTALL_DATA_DIR) bin/docs/html $(DESTDIR)$(PREFIX)/share/doc/libopenmpt/html
|
$(INSTALL_DATA_DIR) bin/docs/html $(DESTDIR)$(PREFIX)/share/doc/libopenmpt/html
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: install-openmpt-modplug
|
|
||||||
install-openmpt-modplug: $(OUTPUTS)
|
|
||||||
ifeq ($(SHARED_LIB),1)
|
|
||||||
$(INSTALL_MAKE_DIR) $(DESTDIR)$(PREFIX)/lib
|
|
||||||
$(INSTALL_LIB) bin/libopenmpt_modplug$(SOSUFFIX) $(DESTDIR)$(PREFIX)/lib/libopenmpt_modplug$(SOSUFFIX)
|
|
||||||
$(INSTALL_LIB) bin/libopenmpt_modplug$(SOSUFFIX) $(DESTDIR)$(PREFIX)/lib/libopenmpt_modplug$(SOSUFFIX).1
|
|
||||||
$(INSTALL_LIB) bin/libopenmpt_modplug$(SOSUFFIX) $(DESTDIR)$(PREFIX)/lib/libopenmpt_modplug$(SOSUFFIX).1.0.0
|
|
||||||
endif
|
|
||||||
|
|
||||||
.PHONY: install-modplug
|
|
||||||
install-modplug: $(OUTPUTS)
|
|
||||||
ifeq ($(SHARED_LIB),1)
|
|
||||||
$(INSTALL_MAKE_DIR) $(DESTDIR)$(PREFIX)/lib
|
|
||||||
$(INSTALL_LIB) bin/libopenmpt_modplug$(SOSUFFIX) $(DESTDIR)$(PREFIX)/lib/libmodplug$(SOSUFFIX)
|
|
||||||
$(INSTALL_LIB) bin/libopenmpt_modplug$(SOSUFFIX) $(DESTDIR)$(PREFIX)/lib/libmodplug$(SOSUFFIX).1
|
|
||||||
$(INSTALL_LIB) bin/libopenmpt_modplug$(SOSUFFIX) $(DESTDIR)$(PREFIX)/lib/libmodplug$(SOSUFFIX).1.0.0
|
|
||||||
endif
|
|
||||||
|
|
||||||
.PHONY: dist
|
.PHONY: dist
|
||||||
dist: bin/dist-tar.tar bin/dist-zip.tar bin/dist-doc.tar
|
dist: bin/dist-tar.tar bin/dist-zip.tar bin/dist-doc.tar
|
||||||
|
|
||||||
|
@ -1209,6 +1304,7 @@ bin/dist-tar/libopenmpt-$(DIST_LIBOPENMPT_VERSION).makefile.tar: bin/dist.mk bin
|
||||||
svn export ./LICENSE bin/dist-tar/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/LICENSE
|
svn export ./LICENSE bin/dist-tar/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/LICENSE
|
||||||
svn export ./README.md bin/dist-tar/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/README.md
|
svn export ./README.md bin/dist-tar/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/README.md
|
||||||
svn export ./Makefile bin/dist-tar/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/Makefile
|
svn export ./Makefile bin/dist-tar/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/Makefile
|
||||||
|
svn export ./.clang-format bin/dist-tar/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/.clang-format
|
||||||
svn export ./bin bin/dist-tar/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/bin
|
svn export ./bin bin/dist-tar/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/bin
|
||||||
svn export ./build/android_ndk bin/dist-tar/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/android_ndk
|
svn export ./build/android_ndk bin/dist-tar/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/android_ndk
|
||||||
svn export ./build/make bin/dist-tar/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/make
|
svn export ./build/make bin/dist-tar/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/make
|
||||||
|
@ -1229,7 +1325,6 @@ bin/dist-tar/libopenmpt-$(DIST_LIBOPENMPT_VERSION).makefile.tar: bin/dist.mk bin
|
||||||
svn export ./include/cwsdpmi bin/dist-tar/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/include/cwsdpmi
|
svn export ./include/cwsdpmi bin/dist-tar/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/include/cwsdpmi
|
||||||
svn export ./include/minimp3 bin/dist-tar/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/include/minimp3
|
svn export ./include/minimp3 bin/dist-tar/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/include/minimp3
|
||||||
svn export ./include/miniz bin/dist-tar/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/include/miniz
|
svn export ./include/miniz bin/dist-tar/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/include/miniz
|
||||||
svn export ./include/modplug bin/dist-tar/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/include/modplug
|
|
||||||
svn export ./include/stb_vorbis bin/dist-tar/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/include/stb_vorbis
|
svn export ./include/stb_vorbis bin/dist-tar/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/include/stb_vorbis
|
||||||
cp bin/dist.mk bin/dist-tar/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/dist.mk
|
cp bin/dist.mk bin/dist-tar/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/dist.mk
|
||||||
cp bin/svn_version_dist.h bin/dist-tar/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/svn_version/svn_version.h
|
cp bin/svn_version_dist.h bin/dist-tar/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/svn_version/svn_version.h
|
||||||
|
@ -1248,6 +1343,7 @@ bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION).msvc.zip: bin/dist.mk bin/svn
|
||||||
svn export ./LICENSE bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/LICENSE --native-eol CRLF
|
svn export ./LICENSE bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/LICENSE --native-eol CRLF
|
||||||
svn export ./README.md bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/README.md --native-eol CRLF
|
svn export ./README.md bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/README.md --native-eol CRLF
|
||||||
svn export ./Makefile bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/Makefile --native-eol CRLF
|
svn export ./Makefile bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/Makefile --native-eol CRLF
|
||||||
|
svn export ./.clang-format bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/.clang-format --native-eol CRLF
|
||||||
svn export ./bin bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/bin --native-eol CRLF
|
svn export ./bin bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/bin --native-eol CRLF
|
||||||
svn export ./build/genie/def bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/genie/def --native-eol CRLF
|
svn export ./build/genie/def bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/genie/def --native-eol CRLF
|
||||||
svn export ./build/premake/def bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/premake/def --native-eol CRLF
|
svn export ./build/premake/def bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/premake/def --native-eol CRLF
|
||||||
|
@ -1257,13 +1353,14 @@ bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION).msvc.zip: bin/dist.mk bin/svn
|
||||||
svn export ./build/svn_version bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/svn_version --native-eol CRLF
|
svn export ./build/svn_version bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/svn_version --native-eol CRLF
|
||||||
svn export ./build/vcpkg bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/vcpkg --native-eol CRLF
|
svn export ./build/vcpkg bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/vcpkg --native-eol CRLF
|
||||||
svn export ./build/vs bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/vs --native-eol CRLF
|
svn export ./build/vs bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/vs --native-eol CRLF
|
||||||
svn export ./build/vs2015 bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/vs2015 --native-eol CRLF
|
svn export ./build/vs2017win7 bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/vs2017win7 --native-eol CRLF
|
||||||
svn export ./build/vs2015xp bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/vs2015xp --native-eol CRLF
|
svn export ./build/vs2017win81 bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/vs2017win81 --native-eol CRLF
|
||||||
svn export ./build/vs2017 bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/vs2017 --native-eol CRLF
|
svn export ./build/vs2017win10 bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/vs2017win10 --native-eol CRLF
|
||||||
svn export ./build/vs2017win10 bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/vs2017win10
|
svn export ./build/vs2017uwp bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/vs2017uwp --native-eol CRLF
|
||||||
svn export ./build/vs2017xp bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/vs2017xp --native-eol CRLF
|
svn export ./build/vs2019win7 bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/vs2019win7 --native-eol CRLF
|
||||||
svn export ./build/windesktop81 bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/windesktop81 --native-eol CRLF
|
svn export ./build/vs2019win81 bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/vs2019win81 --native-eol CRLF
|
||||||
svn export ./build/winstore82 bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/winstore82 --native-eol CRLF
|
svn export ./build/vs2019win10 bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/vs2019win10 --native-eol CRLF
|
||||||
|
svn export ./build/vs2019uwp bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/vs2019uwp --native-eol CRLF
|
||||||
svn export ./build/download_externals.cmd bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/download_externals.cmd --native-eol CRLF
|
svn export ./build/download_externals.cmd bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/download_externals.cmd --native-eol CRLF
|
||||||
svn export ./common bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/common --native-eol CRLF
|
svn export ./common bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/common --native-eol CRLF
|
||||||
svn export ./doc/contributing.md bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/doc/contributing.md --native-eol CRLF
|
svn export ./doc/contributing.md bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/doc/contributing.md --native-eol CRLF
|
||||||
|
@ -1282,8 +1379,6 @@ bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION).msvc.zip: bin/dist.mk bin/svn
|
||||||
svn export ./include/mpg123 bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/include/mpg123 --native-eol CRLF
|
svn export ./include/mpg123 bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/include/mpg123 --native-eol CRLF
|
||||||
svn export ./include/flac bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/include/flac --native-eol CRLF
|
svn export ./include/flac bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/include/flac --native-eol CRLF
|
||||||
svn export ./include/portaudio bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/include/portaudio --native-eol CRLF
|
svn export ./include/portaudio bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/include/portaudio --native-eol CRLF
|
||||||
svn export ./include/modplug bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/include/modplug --native-eol CRLF
|
|
||||||
svn export ./include/foobar2000sdk bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/include/foobar2000sdk --native-eol CRLF
|
|
||||||
svn export ./include/ogg bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/include/ogg --native-eol CRLF
|
svn export ./include/ogg bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/include/ogg --native-eol CRLF
|
||||||
svn export ./include/pugixml bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/include/pugixml --native-eol CRLF
|
svn export ./include/pugixml bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/include/pugixml --native-eol CRLF
|
||||||
svn export ./include/stb_vorbis bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/include/stb_vorbis --native-eol CRLF
|
svn export ./include/stb_vorbis bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/include/stb_vorbis --native-eol CRLF
|
||||||
|
@ -1314,15 +1409,14 @@ bin/dist-js/libopenmpt-$(DIST_LIBOPENMPT_VERSION).dev.js.tar:
|
||||||
svn export ./include/miniz/miniz.c bin/dist-js/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/licenses/license.miniz.txt
|
svn export ./include/miniz/miniz.c bin/dist-js/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/licenses/license.miniz.txt
|
||||||
svn export ./include/stb_vorbis/stb_vorbis.c bin/dist-js/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/licenses/license.stb_vorbis.txt
|
svn export ./include/stb_vorbis/stb_vorbis.c bin/dist-js/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/licenses/license.stb_vorbis.txt
|
||||||
mkdir -p bin/dist-js/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/bin
|
mkdir -p bin/dist-js/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/bin
|
||||||
|
mkdir -p bin/dist-js/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/bin/all
|
||||||
|
cp bin/stage/all/libopenmpt.js bin/dist-js/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/bin/all/libopenmpt.js
|
||||||
|
cp bin/stage/all/libopenmpt.js.mem bin/dist-js/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/bin/all/libopenmpt.js.mem
|
||||||
|
cp bin/stage/all/libopenmpt.wasm bin/dist-js/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/bin/all/libopenmpt.wasm
|
||||||
|
cp bin/stage/all/libopenmpt.wasm.js bin/dist-js/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/bin/all/libopenmpt.wasm.js
|
||||||
mkdir -p bin/dist-js/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/bin/wasm
|
mkdir -p bin/dist-js/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/bin/wasm
|
||||||
cp bin/stage/wasm/libopenmpt.js bin/dist-js/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/bin/wasm/libopenmpt.js
|
cp bin/stage/wasm/libopenmpt.js bin/dist-js/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/bin/wasm/libopenmpt.js
|
||||||
cp bin/stage/wasm/libopenmpt.wasm bin/dist-js/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/bin/wasm/libopenmpt.wasm
|
cp bin/stage/wasm/libopenmpt.wasm bin/dist-js/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/bin/wasm/libopenmpt.wasm
|
||||||
mkdir -p bin/dist-js/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/bin/asmjs128m
|
|
||||||
cp bin/stage/asmjs128m/libopenmpt.js bin/dist-js/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/bin/asmjs128m/libopenmpt.js
|
|
||||||
cp bin/stage/asmjs128m/libopenmpt.js.mem bin/dist-js/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/bin/asmjs128m/libopenmpt.js.mem
|
|
||||||
mkdir -p bin/dist-js/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/bin/asmjs
|
|
||||||
cp bin/stage/asmjs/libopenmpt.js bin/dist-js/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/bin/asmjs/libopenmpt.js
|
|
||||||
cp bin/stage/asmjs/libopenmpt.js.mem bin/dist-js/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/bin/asmjs/libopenmpt.js.mem
|
|
||||||
mkdir -p bin/dist-js/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/bin/js
|
mkdir -p bin/dist-js/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/bin/js
|
||||||
cp bin/stage/js/libopenmpt.js bin/dist-js/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/bin/js/libopenmpt.js
|
cp bin/stage/js/libopenmpt.js bin/dist-js/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/bin/js/libopenmpt.js
|
||||||
cp bin/stage/js/libopenmpt.js.mem bin/dist-js/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/bin/js/libopenmpt.js.mem
|
cp bin/stage/js/libopenmpt.js.mem bin/dist-js/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/bin/js/libopenmpt.js.mem
|
||||||
|
@ -1361,16 +1455,16 @@ bin/libopenmpt.a: $(LIBOPENMPT_OBJECTS)
|
||||||
|
|
||||||
bin/libopenmpt$(SOSUFFIX): $(LIBOPENMPT_OBJECTS)
|
bin/libopenmpt$(SOSUFFIX): $(LIBOPENMPT_OBJECTS)
|
||||||
$(INFO) [LD] $@
|
$(INFO) [LD] $@
|
||||||
|
ifeq ($(NO_SHARED_LINKER_FLAG),1)
|
||||||
|
$(SILENT)$(LINK.cc) $(LIBOPENMPT_LDFLAGS) $(SO_LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@
|
||||||
|
else
|
||||||
$(SILENT)$(LINK.cc) -shared $(LIBOPENMPT_LDFLAGS) $(SO_LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@
|
$(SILENT)$(LINK.cc) -shared $(LIBOPENMPT_LDFLAGS) $(SO_LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@
|
||||||
|
endif
|
||||||
ifeq ($(SHARED_SONAME),1)
|
ifeq ($(SHARED_SONAME),1)
|
||||||
$(SILENT)mv bin/libopenmpt$(SOSUFFIX) bin/$(LIBOPENMPT_SONAME)
|
$(SILENT)mv bin/libopenmpt$(SOSUFFIX) bin/$(LIBOPENMPT_SONAME)
|
||||||
$(SILENT)ln -sf $(LIBOPENMPT_SONAME) bin/libopenmpt$(SOSUFFIX)
|
$(SILENT)ln -sf $(LIBOPENMPT_SONAME) bin/libopenmpt$(SOSUFFIX)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
bin/libopenmpt_modplug$(SOSUFFIX): $(LIBOPENMPT_MODPLUG_OBJECTS) $(OUTPUT_LIBOPENMPT)
|
|
||||||
$(INFO) [LD] $@
|
|
||||||
$(SILENT)$(LINK.cc) -shared $(SO_LDFLAGS) $(LDFLAGS_LIBOPENMPT) $(LIBOPENMPT_MODPLUG_OBJECTS) $(OBJECTS_LIBOPENMPT) $(LOADLIBES) $(LDLIBS) $(LDLIBS_LIBOPENMPT) -o $@
|
|
||||||
|
|
||||||
bin/openmpt123.1: bin/openmpt123$(EXESUFFIX) openmpt123/openmpt123.h2m
|
bin/openmpt123.1: bin/openmpt123$(EXESUFFIX) openmpt123/openmpt123.h2m
|
||||||
$(INFO) [HELP2MAN] $@
|
$(INFO) [HELP2MAN] $@
|
||||||
$(SILENT)help2man --no-discard-stderr --no-info --version-option=--man-version --help-option=--man-help --include=openmpt123/openmpt123.h2m $< > $@
|
$(SILENT)help2man --no-discard-stderr --no-info --version-option=--man-version --help-option=--man-help --include=openmpt123/openmpt123.h2m $< > $@
|
||||||
|
|
|
@ -35,44 +35,19 @@ How to compile
|
||||||
|
|
||||||
- Supported Visual Studio versions:
|
- Supported Visual Studio versions:
|
||||||
|
|
||||||
- Visual Studio 2015 Update 3 Community/Professional/Enterprise
|
- Visual Studio 2017 and 2019 Community/Professional/Enterprise
|
||||||
|
|
||||||
To compile the project, open `build/vs2015/OpenMPT.sln` and hit the
|
To compile the project, open `build/vsVERSIONwin7/OpenMPT.sln` (VERSION
|
||||||
compile button.
|
being 2017 or 2019) and hit the compile button. Other target systems can
|
||||||
|
be found in the `vs2017*` and `vs2019*` sibling folders.
|
||||||
- Visual Studio 2017 Community/Professional/Enterprise
|
|
||||||
|
|
||||||
To compile the project, open `build/vs2017/OpenMPT.sln` and hit the
|
|
||||||
compile button.
|
|
||||||
|
|
||||||
- OpenMPT requires the compile host system to be 64bit x86-64.
|
- OpenMPT requires the compile host system to be 64bit x86-64.
|
||||||
|
|
||||||
- The Windows 8.1 SDK and Microsoft Foundation Classes (MFC) are required to
|
- The Windows 8.1 SDK is required to build OpenMPT with Visual Studio 2017
|
||||||
build OpenMPT (both are included with Visual Studio, however may need to be
|
(this is included with Visual Studio, however may need to be selected
|
||||||
selected explicitly during setup). In order to build OpenMPT for Windows XP,
|
explicitly during setup).
|
||||||
the XP targetting toolset also needs to be installed.
|
|
||||||
|
|
||||||
- The ASIO SDK is needed for compiling with ASIO support.
|
- Microsoft Foundation Classes (MFC) are required to build OpenMPT.
|
||||||
|
|
||||||
If you don't want this, comment out `#define MPT_WITH_ASIO` in the file
|
|
||||||
`common/BuildSettings.h`.
|
|
||||||
|
|
||||||
The ASIO SDK can be downloaded automatically on Windows 7 or later by just
|
|
||||||
running the `build/download_externals.cmd` script.
|
|
||||||
|
|
||||||
If you do not want to or cannot use this script, you may follow these manual
|
|
||||||
steps instead:
|
|
||||||
|
|
||||||
- Visit
|
|
||||||
[steinberg.net](https://www.steinberg.net/en/company/developers.html) to
|
|
||||||
download the SDK.
|
|
||||||
|
|
||||||
- Put the ASIO SDK in the `include/ASIOSDK2` folder. The top level
|
|
||||||
directory of the SDK is already named `ASIOSDK2`, so simply move that
|
|
||||||
directory in the include folder.
|
|
||||||
|
|
||||||
If you need further help with the ASIO SDK, get in touch with the
|
|
||||||
main OpenMPT developers.
|
|
||||||
|
|
||||||
|
|
||||||
### libopenmpt and openmpt123
|
### libopenmpt and openmpt123
|
||||||
|
@ -104,15 +79,13 @@ For detailed requirements, see `libopenmpt/dox/quickstart.md`.
|
||||||
|
|
||||||
- Visual Studio:
|
- Visual Studio:
|
||||||
|
|
||||||
- You will find solutions for Visual Studio 2015 to 2017 in the
|
- You will find solutions for Visual Studio 2017 and 2019 in the
|
||||||
corresponding `build/vsVERSION/` folder.
|
corresponding `build/vsVERSIONwin7/` folder.
|
||||||
Projects that target Windows versions before Windows 7 are available in
|
Projects that target Windows 10 Desktop (including ARM and ARM64) are
|
||||||
`build/vsVERSIONxp/`.
|
available in `build/vsVERSIONwin10/` (Visual Studio 2017 requires SDK
|
||||||
Projects that target Windows 10 1709 Desktop (10.0.16299.0, including
|
version 10.0.16299).
|
||||||
ARM and ARM64) or later versions are available in
|
|
||||||
`build/vsVERSIONwin10/`.
|
|
||||||
Minimal projects that target Windows 10 UWP are available in
|
Minimal projects that target Windows 10 UWP are available in
|
||||||
`build/winstore82/`.
|
`build/vsVERSIONuwp/`.
|
||||||
Most projects are supported with any of the mentioned Visual Studio
|
Most projects are supported with any of the mentioned Visual Studio
|
||||||
verions, with the following exceptions:
|
verions, with the following exceptions:
|
||||||
|
|
||||||
|
@ -161,7 +134,7 @@ For detailed requirements, see `libopenmpt/dox/quickstart.md`.
|
||||||
|
|
||||||
- mingw-w64:
|
- mingw-w64:
|
||||||
|
|
||||||
The required version is at least 4.8.
|
The required compiler version is at least GCC 7.
|
||||||
|
|
||||||
make CONFIG=mingw64-win32 # for win32
|
make CONFIG=mingw64-win32 # for win32
|
||||||
|
|
||||||
|
@ -172,9 +145,9 @@ For detailed requirements, see `libopenmpt/dox/quickstart.md`.
|
||||||
|
|
||||||
The minimum required compiler versions are:
|
The minimum required compiler versions are:
|
||||||
|
|
||||||
- gcc 4.8
|
- gcc 7
|
||||||
|
|
||||||
- clang 3.6
|
- clang 5
|
||||||
|
|
||||||
The Makefile requires pkg-config for native builds.
|
The Makefile requires pkg-config for native builds.
|
||||||
For sound output in openmpt123, PortAudio or SDL is required.
|
For sound output in openmpt123, PortAudio or SDL is required.
|
||||||
|
@ -256,7 +229,7 @@ For detailed requirements, see `libopenmpt/dox/quickstart.md`.
|
||||||
|
|
||||||
- other compilers:
|
- other compilers:
|
||||||
|
|
||||||
To compile libopenmpt with other C++11 compliant compilers, run:
|
To compile libopenmpt with other C++14 compliant compilers, run:
|
||||||
|
|
||||||
make CONFIG=generic
|
make CONFIG=generic
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ include $(CLEAR_VARS)
|
||||||
LOCAL_MODULE := openmpt
|
LOCAL_MODULE := openmpt
|
||||||
|
|
||||||
LOCAL_CFLAGS +=#-std=c99
|
LOCAL_CFLAGS +=#-std=c99
|
||||||
LOCAL_CPPFLAGS += -std=c++11 -fexceptions -frtti
|
LOCAL_CPPFLAGS += -std=c++17 -fexceptions -frtti
|
||||||
|
|
||||||
LOCAL_CPP_FEATURES += exceptions rtti
|
LOCAL_CPP_FEATURES += exceptions rtti
|
||||||
|
|
||||||
|
@ -111,12 +111,12 @@ LOCAL_SRC_FILES += \
|
||||||
libopenmpt/libopenmpt_cxx.cpp \
|
libopenmpt/libopenmpt_cxx.cpp \
|
||||||
libopenmpt/libopenmpt_impl.cpp \
|
libopenmpt/libopenmpt_impl.cpp \
|
||||||
libopenmpt/libopenmpt_ext_impl.cpp \
|
libopenmpt/libopenmpt_ext_impl.cpp \
|
||||||
|
soundbase/Dither.cpp \
|
||||||
soundlib/AudioCriticalSection.cpp \
|
soundlib/AudioCriticalSection.cpp \
|
||||||
soundlib/ContainerMMCMP.cpp \
|
soundlib/ContainerMMCMP.cpp \
|
||||||
soundlib/ContainerPP20.cpp \
|
soundlib/ContainerPP20.cpp \
|
||||||
soundlib/ContainerUMX.cpp \
|
soundlib/ContainerUMX.cpp \
|
||||||
soundlib/ContainerXPK.cpp \
|
soundlib/ContainerXPK.cpp \
|
||||||
soundlib/Dither.cpp \
|
|
||||||
soundlib/Dlsbank.cpp \
|
soundlib/Dlsbank.cpp \
|
||||||
soundlib/Fastmix.cpp \
|
soundlib/Fastmix.cpp \
|
||||||
soundlib/InstrumentExtensions.cpp \
|
soundlib/InstrumentExtensions.cpp \
|
||||||
|
@ -178,10 +178,12 @@ LOCAL_SRC_FILES += \
|
||||||
soundlib/RowVisitor.cpp \
|
soundlib/RowVisitor.cpp \
|
||||||
soundlib/S3MTools.cpp \
|
soundlib/S3MTools.cpp \
|
||||||
soundlib/SampleFormats.cpp \
|
soundlib/SampleFormats.cpp \
|
||||||
|
soundlib/SampleFormatBRR.cpp \
|
||||||
soundlib/SampleFormatFLAC.cpp \
|
soundlib/SampleFormatFLAC.cpp \
|
||||||
soundlib/SampleFormatMediaFoundation.cpp \
|
soundlib/SampleFormatMediaFoundation.cpp \
|
||||||
soundlib/SampleFormatMP3.cpp \
|
soundlib/SampleFormatMP3.cpp \
|
||||||
soundlib/SampleFormatOpus.cpp \
|
soundlib/SampleFormatOpus.cpp \
|
||||||
|
soundlib/SampleFormatSFZ.cpp \
|
||||||
soundlib/SampleFormatVorbis.cpp \
|
soundlib/SampleFormatVorbis.cpp \
|
||||||
soundlib/SampleIO.cpp \
|
soundlib/SampleIO.cpp \
|
||||||
soundlib/Sndfile.cpp \
|
soundlib/Sndfile.cpp \
|
||||||
|
@ -193,7 +195,7 @@ LOCAL_SRC_FILES += \
|
||||||
soundlib/UpgradeModule.cpp \
|
soundlib/UpgradeModule.cpp \
|
||||||
soundlib/Tables.cpp \
|
soundlib/Tables.cpp \
|
||||||
soundlib/Tagging.cpp \
|
soundlib/Tagging.cpp \
|
||||||
soundlib/tuningbase.cpp \
|
soundlib/TinyFFT.cpp \
|
||||||
soundlib/tuningCollection.cpp \
|
soundlib/tuningCollection.cpp \
|
||||||
soundlib/tuning.cpp \
|
soundlib/tuning.cpp \
|
||||||
soundlib/WAVTools.cpp \
|
soundlib/WAVTools.cpp \
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
APP_CFLAGS :=#-std=c99
|
APP_CFLAGS :=#-std=c99
|
||||||
APP_CPPFLAGS := -std=c++11 -fexceptions -frtti
|
APP_CPPFLAGS := -std=c++17 -fexceptions -frtti
|
||||||
APP_LDFLAGS :=
|
APP_LDFLAGS :=
|
||||||
APP_STL := c++_shared
|
APP_STL := c++_shared
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
This is preliminary documentation.
|
This is preliminary documentation.
|
||||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
|
||||||
0. The minimum required Android NDK version is r16b.
|
0. The minimum required Android NDK version is r18b.
|
||||||
1. Copy the whole libopenmpt source tree below your jni directory.
|
1. Copy the whole libopenmpt source tree below your jni directory.
|
||||||
2. Copy build/android_ndk/* into the root of libopenmpt, i.e. also into the
|
2. Copy build/android_ndk/* into the root of libopenmpt, i.e. also into the
|
||||||
jni directory and adjust as needed.
|
jni directory and adjust as needed.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
|
|
||||||
MPT_SVNVERSION=12263
|
MPT_SVNVERSION=13555
|
||||||
MPT_SVNURL=https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.4.10
|
MPT_SVNURL=https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.5.2
|
||||||
MPT_SVNDATE=2019-10-30T10:43:15.521271Z
|
MPT_SVNDATE=2020-08-30T13:42:32.941871Z
|
||||||
|
|
|
@ -9,14 +9,6 @@ CXXFLAGS_STDCXX = -std=$(STDCXX)
|
||||||
else
|
else
|
||||||
ifeq ($(shell printf '\n' > bin/empty.cpp ; if $(CXX) -std=c++17 -c bin/empty.cpp -o bin/empty.out > /dev/null 2>&1 ; then echo 'c++17' ; fi ), c++17)
|
ifeq ($(shell printf '\n' > bin/empty.cpp ; if $(CXX) -std=c++17 -c bin/empty.cpp -o bin/empty.out > /dev/null 2>&1 ; then echo 'c++17' ; fi ), c++17)
|
||||||
CXXFLAGS_STDCXX = -std=c++17
|
CXXFLAGS_STDCXX = -std=c++17
|
||||||
else
|
|
||||||
ifeq ($(shell printf '\n' > bin/empty.cpp ; if $(CXX) -std=c++14 -c bin/empty.cpp -o bin/empty.out > /dev/null 2>&1 ; then echo 'c++14' ; fi ), c++14)
|
|
||||||
CXXFLAGS_STDCXX = -std=c++14
|
|
||||||
else
|
|
||||||
ifeq ($(shell printf '\n' > bin/empty.cpp ; if $(CXX) -std=c++11 -c bin/empty.cpp -o bin/empty.out > /dev/null 2>&1 ; then echo 'c++11' ; fi ), c++11)
|
|
||||||
CXXFLAGS_STDCXX = -std=c++11
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
CFLAGS_STDC = -std=c99
|
CFLAGS_STDC = -std=c99
|
||||||
|
|
|
@ -12,10 +12,6 @@ CXXFLAGS_STDCXX = -std=c++17
|
||||||
else
|
else
|
||||||
ifeq ($(shell printf '\n' > bin/empty.cpp ; if $(CXX) -std=c++14 -c bin/empty.cpp -o bin/empty.out > /dev/null 2>&1 ; then echo 'c++14' ; fi ), c++14)
|
ifeq ($(shell printf '\n' > bin/empty.cpp ; if $(CXX) -std=c++14 -c bin/empty.cpp -o bin/empty.out > /dev/null 2>&1 ; then echo 'c++14' ; fi ), c++14)
|
||||||
CXXFLAGS_STDCXX = -std=c++14
|
CXXFLAGS_STDCXX = -std=c++14
|
||||||
else
|
|
||||||
ifeq ($(shell printf '\n' > bin/empty.cpp ; if $(CXX) -std=c++11 -c bin/empty.cpp -o bin/empty.out > /dev/null 2>&1 ; then echo 'c++11' ; fi ), c++11)
|
|
||||||
CXXFLAGS_STDCXX = -std=c++11
|
|
||||||
endif
|
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
@ -43,20 +39,27 @@ endif
|
||||||
CXXFLAGS_WARNINGS += -Wmissing-declarations -Wshift-count-negative -Wshift-count-overflow -Wshift-overflow -Wshift-sign-overflow -Wshift-op-parentheses
|
CXXFLAGS_WARNINGS += -Wmissing-declarations -Wshift-count-negative -Wshift-count-overflow -Wshift-overflow -Wshift-sign-overflow -Wshift-op-parentheses
|
||||||
CFLAGS_WARNINGS += -Wmissing-prototypes -Wshift-count-negative -Wshift-count-overflow -Wshift-overflow -Wshift-sign-overflow -Wshift-op-parentheses
|
CFLAGS_WARNINGS += -Wmissing-prototypes -Wshift-count-negative -Wshift-count-overflow -Wshift-overflow -Wshift-sign-overflow -Wshift-op-parentheses
|
||||||
|
|
||||||
|
CXXFLAGS_WARNINGS += -Wdeprecated -Wextra-semi -Wnon-virtual-dtor -Wreserved-id-macro -Wglobal-constructors -Wimplicit-fallthrough
|
||||||
|
|
||||||
#CXXFLAGS_WARNINGS += -Wdocumentation
|
#CXXFLAGS_WARNINGS += -Wdocumentation
|
||||||
#CXXFLAGS_WARNINGS += -Wconversion
|
#CXXFLAGS_WARNINGS += -Wconversion
|
||||||
#CXXFLAGS_WARNINGS += -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-padded -Wno-shadow -Wno-sign-conversion -Wno-weak-vtables
|
#CXXFLAGS_WARNINGS += -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-padded -Wno-shadow -Wno-sign-conversion -Wno-weak-vtables
|
||||||
|
|
||||||
ifeq ($(MODERN),1)
|
ifeq ($(MODERN),1)
|
||||||
LDFLAGS += -fuse-ld=lld
|
LDFLAGS += -fuse-ld=lld
|
||||||
CXXFLAGS_WARNINGS += -Wpedantic -Wframe-larger-than=20000
|
CXXFLAGS_WARNINGS += -Wpedantic -Wframe-larger-than=16000
|
||||||
#CXXFLAGS_WARNINGS += -Wdouble-promotion -Wframe-larger-than=16000
|
|
||||||
CFLAGS_WARNINGS += -Wpedantic -Wframe-larger-than=4000
|
CFLAGS_WARNINGS += -Wpedantic -Wframe-larger-than=4000
|
||||||
#CFLAGS_WARNINGS += -Wdouble-promotion
|
|
||||||
LDFLAGS_WARNINGS += -Wl,-no-undefined -Wl,--detect-odr-violations
|
LDFLAGS_WARNINGS += -Wl,-no-undefined -Wl,--detect-odr-violations
|
||||||
CXXFLAGS_WARNINGS += -Wdeprecated -Wextra-semi -Wnon-virtual-dtor -Wreserved-id-macro
|
# re-renable after 1.29 branch
|
||||||
|
#CXXFLAGS_WARNINGS += -Wdouble-promotion
|
||||||
|
#CFLAGS_WARNINGS += -Wdouble-promotion
|
||||||
endif
|
endif
|
||||||
|
|
||||||
CFLAGS_SILENT += -Wno-unused-parameter -Wno-unused-function -Wno-cast-qual
|
CFLAGS_SILENT += -Wno-cast-align
|
||||||
|
CFLAGS_SILENT += -Wno-cast-qual
|
||||||
|
CFLAGS_SILENT += -Wno-missing-prototypes
|
||||||
|
CFLAGS_SILENT += -Wno-sign-compare
|
||||||
|
CFLAGS_SILENT += -Wno-unused-function
|
||||||
|
CFLAGS_SILENT += -Wno-unused-parameter
|
||||||
|
|
||||||
EXESUFFIX=
|
EXESUFFIX=
|
||||||
|
|
|
@ -7,9 +7,6 @@ include build/make/config-clang.mk
|
||||||
# Mac OS X overrides
|
# Mac OS X overrides
|
||||||
DYNLINK=0
|
DYNLINK=0
|
||||||
SHARED_SONAME=0
|
SHARED_SONAME=0
|
||||||
# when using iconv
|
|
||||||
#CPPFLAGS += -DMPT_WITH_ICONV
|
|
||||||
#LDLIBS += -liconv
|
|
||||||
|
|
||||||
else ifeq ($(HOST_FLAVOUR),LINUX)
|
else ifeq ($(HOST_FLAVOUR),LINUX)
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
|
|
||||||
CC = i586-pc-msdosdjgpp-gcc
|
CC = i386-pc-msdosdjgpp-gcc
|
||||||
CXX = i586-pc-msdosdjgpp-g++
|
CXX = i386-pc-msdosdjgpp-g++
|
||||||
LD = i586-pc-msdosdjgpp-g++
|
LD = i386-pc-msdosdjgpp-g++
|
||||||
AR = i586-pc-msdosdjgpp-ar
|
AR = i386-pc-msdosdjgpp-ar
|
||||||
|
|
||||||
# Note that we are using GNU extensions instead of 100% standards-compliant
|
# Note that we are using GNU extensions instead of 100% standards-compliant
|
||||||
# mode, because otherwise DJGPP-specific headers/functions are unavailable.
|
# mode, because otherwise DJGPP-specific headers/functions are unavailable.
|
||||||
CXXFLAGS_STDCXX = -std=gnu++11
|
CXXFLAGS_STDCXX = -std=gnu++17
|
||||||
CFLAGS_STDC = -std=gnu99
|
CFLAGS_STDC = -std=gnu99
|
||||||
CXXFLAGS += $(CXXFLAGS_STDCXX)
|
CXXFLAGS += $(CXXFLAGS_STDCXX)
|
||||||
CFLAGS += $(CFLAGS_STDC)
|
CFLAGS += $(CFLAGS_STDC)
|
||||||
|
|
||||||
CPPFLAGS +=
|
CPPFLAGS +=
|
||||||
CXXFLAGS += -march=pentium -mtune=pentium
|
CXXFLAGS += -march=i386 -m80387 -mtune=pentium
|
||||||
CFLAGS += -march=pentium -mtune=pentium
|
CFLAGS += -march=i386 -m80387 -mtune=pentium
|
||||||
LDFLAGS +=
|
LDFLAGS +=
|
||||||
LDLIBS += -lm
|
LDLIBS += -lm
|
||||||
ARFLAGS := rcs
|
ARFLAGS := rcs
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
|
|
||||||
CC = emcc
|
CC = emcc -c
|
||||||
CXX = em++
|
CXX = em++ -c
|
||||||
LD = em++
|
LD = em++
|
||||||
AR = emar
|
AR = emar
|
||||||
|
LINK.cc = em++ $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)
|
||||||
|
|
||||||
EMSCRIPTEN_TARGET?=default
|
EMSCRIPTEN_TARGET?=default
|
||||||
|
|
||||||
|
@ -11,14 +12,6 @@ CXXFLAGS_STDCXX = -std=$(STDCXX)
|
||||||
else
|
else
|
||||||
ifeq ($(shell printf '\n' > bin/empty.cpp ; if $(CXX) -std=c++17 -c bin/empty.cpp -o bin/empty.out > /dev/null 2>&1 ; then echo 'c++17' ; fi ), c++17)
|
ifeq ($(shell printf '\n' > bin/empty.cpp ; if $(CXX) -std=c++17 -c bin/empty.cpp -o bin/empty.out > /dev/null 2>&1 ; then echo 'c++17' ; fi ), c++17)
|
||||||
CXXFLAGS_STDCXX = -std=c++17
|
CXXFLAGS_STDCXX = -std=c++17
|
||||||
else
|
|
||||||
ifeq ($(shell printf '\n' > bin/empty.cpp ; if $(CXX) -std=c++14 -c bin/empty.cpp -o bin/empty.out > /dev/null 2>&1 ; then echo 'c++14' ; fi ), c++14)
|
|
||||||
CXXFLAGS_STDCXX = -std=c++14
|
|
||||||
else
|
|
||||||
ifeq ($(shell printf '\n' > bin/empty.cpp ; if $(CXX) -std=c++11 -c bin/empty.cpp -o bin/empty.out > /dev/null 2>&1 ; then echo 'c++11' ; fi ), c++11)
|
|
||||||
CXXFLAGS_STDCXX = -std=c++11
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
CFLAGS_STDC = -std=c99
|
CFLAGS_STDC = -std=c99
|
||||||
|
@ -45,50 +38,49 @@ LDFLAGS +=
|
||||||
|
|
||||||
LDFLAGS += -s ALLOW_MEMORY_GROWTH=1
|
LDFLAGS += -s ALLOW_MEMORY_GROWTH=1
|
||||||
|
|
||||||
else ifeq ($(EMSCRIPTEN_TARGET),wasm)
|
else ifeq ($(EMSCRIPTEN_TARGET),all)
|
||||||
# emits native wasm AND an emulator for running wasm in asmjs/js with full wasm optimizations.
|
# emits native wasm AND javascript with full wasm optimizations.
|
||||||
# as of emscripten 1.38, this is equivalent to default.
|
# as of emscripten 1.38, this is equivalent to default.
|
||||||
CPPFLAGS += -DMPT_BUILD_WASM
|
CPPFLAGS += -DMPT_BUILD_WASM
|
||||||
CXXFLAGS += -s WASM=1 -s BINARYEN_METHOD='native-wasm'
|
CXXFLAGS += -s WASM=2 -s LEGACY_VM_SUPPORT=1
|
||||||
CFLAGS += -s WASM=1 -s BINARYEN_METHOD='native-wasm'
|
CFLAGS += -s WASM=2 -s LEGACY_VM_SUPPORT=1
|
||||||
LDFLAGS += -s WASM=1 -s BINARYEN_METHOD='native-wasm'
|
LDFLAGS += -s WASM=2 -s LEGACY_VM_SUPPORT=1
|
||||||
|
|
||||||
LDFLAGS += -s ALLOW_MEMORY_GROWTH=1
|
LDFLAGS += -s ALLOW_MEMORY_GROWTH=1
|
||||||
|
|
||||||
else ifeq ($(EMSCRIPTEN_TARGET),asmjs128m)
|
else ifeq ($(EMSCRIPTEN_TARGET),wasm)
|
||||||
# emits only asmjs
|
# emits native wasm.
|
||||||
CPPFLAGS += -DMPT_BUILD_ASMJS
|
CPPFLAGS += -DMPT_BUILD_WASM
|
||||||
CXXFLAGS += -s WASM=0 -s ASM_JS=1
|
CXXFLAGS += -s WASM=1
|
||||||
CFLAGS += -s WASM=0 -s ASM_JS=1
|
CFLAGS += -s WASM=1
|
||||||
LDFLAGS += -s WASM=0 -s ASM_JS=1
|
LDFLAGS += -s WASM=1
|
||||||
|
|
||||||
LDFLAGS += -s ALLOW_MEMORY_GROWTH=0 -s ABORTING_MALLOC=0 -s TOTAL_MEMORY=134217728
|
LDFLAGS += -s ALLOW_MEMORY_GROWTH=1
|
||||||
|
|
||||||
else ifeq ($(EMSCRIPTEN_TARGET),asmjs)
|
|
||||||
# emits only asmjs
|
|
||||||
CPPFLAGS += -DMPT_BUILD_ASMJS
|
|
||||||
CXXFLAGS += -s WASM=0 -s ASM_JS=1
|
|
||||||
CFLAGS += -s WASM=0 -s ASM_JS=1
|
|
||||||
LDFLAGS += -s WASM=0 -s ASM_JS=1
|
|
||||||
|
|
||||||
LDFLAGS += -s ALLOW_MEMORY_GROWTH=0 -s ABORTING_MALLOC=0
|
|
||||||
|
|
||||||
else ifeq ($(EMSCRIPTEN_TARGET),js)
|
else ifeq ($(EMSCRIPTEN_TARGET),js)
|
||||||
# emits only plain javascript with plain javascript focused optimizations.
|
# emits only plain javascript with plain javascript focused optimizations.
|
||||||
CPPFLAGS += -DMPT_BUILD_ASMJS
|
CPPFLAGS += -DMPT_BUILD_ASMJS
|
||||||
CXXFLAGS += -s WASM=0 -s ASM_JS=2 -s LEGACY_VM_SUPPORT=1
|
CXXFLAGS += -s WASM=0 -s LEGACY_VM_SUPPORT=1
|
||||||
CFLAGS += -s WASM=0 -s ASM_JS=2 -s LEGACY_VM_SUPPORT=1
|
CFLAGS += -s WASM=0 -s LEGACY_VM_SUPPORT=1
|
||||||
LDFLAGS += -s WASM=0 -s ASM_JS=2 -s LEGACY_VM_SUPPORT=1
|
LDFLAGS += -s WASM=0 -s LEGACY_VM_SUPPORT=1
|
||||||
|
|
||||||
LDFLAGS += -s ALLOW_MEMORY_GROWTH=1
|
LDFLAGS += -s ALLOW_MEMORY_GROWTH=1
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
CXXFLAGS += -s DISABLE_EXCEPTION_CATCHING=0 -s ERROR_ON_UNDEFINED_SYMBOLS=1 -ffast-math
|
CXXFLAGS += -s DISABLE_EXCEPTION_CATCHING=0 -s ERROR_ON_UNDEFINED_SYMBOLS=1 -s ERROR_ON_MISSING_LIBRARIES=1 -ffast-math
|
||||||
CFLAGS += -s DISABLE_EXCEPTION_CATCHING=0 -s ERROR_ON_UNDEFINED_SYMBOLS=1 -ffast-math -fno-strict-aliasing
|
CFLAGS += -s DISABLE_EXCEPTION_CATCHING=0 -s ERROR_ON_UNDEFINED_SYMBOLS=1 -s ERROR_ON_MISSING_LIBRARIES=1 -ffast-math -fno-strict-aliasing
|
||||||
LDFLAGS += -s DISABLE_EXCEPTION_CATCHING=0 -s ERROR_ON_UNDEFINED_SYMBOLS=1 -s EXPORT_NAME="'libopenmpt'"
|
LDFLAGS += -s DISABLE_EXCEPTION_CATCHING=0 -s ERROR_ON_UNDEFINED_SYMBOLS=1 -s ERROR_ON_MISSING_LIBRARIES=1 -s EXPORT_NAME="'libopenmpt'"
|
||||||
|
|
||||||
CFLAGS_SILENT += -Wno-unused-parameter -Wno-unused-function -Wno-cast-qual
|
CFLAGS_SILENT += -Wno-\#warnings
|
||||||
|
CFLAGS_SILENT += -Wno-cast-align
|
||||||
|
CFLAGS_SILENT += -Wno-cast-qual
|
||||||
|
CFLAGS_SILENT += -Wno-format
|
||||||
|
CFLAGS_SILENT += -Wno-missing-prototypes
|
||||||
|
CFLAGS_SILENT += -Wno-sign-compare
|
||||||
|
CFLAGS_SILENT += -Wno-unused-function
|
||||||
|
CFLAGS_SILENT += -Wno-unused-parameter
|
||||||
|
CFLAGS_SILENT += -Wno-unused-variable
|
||||||
|
|
||||||
CXXFLAGS_WARNINGS += -Wmissing-declarations
|
CXXFLAGS_WARNINGS += -Wmissing-declarations
|
||||||
CFLAGS_WARNINGS += -Wmissing-prototypes
|
CFLAGS_WARNINGS += -Wmissing-prototypes
|
||||||
|
@ -98,7 +90,7 @@ REQUIRES_RUNPREFIX=1
|
||||||
EXESUFFIX=.js
|
EXESUFFIX=.js
|
||||||
SOSUFFIX=.js
|
SOSUFFIX=.js
|
||||||
RUNPREFIX=node
|
RUNPREFIX=node
|
||||||
TEST_LDFLAGS= --pre-js build/make/test-pre.js
|
TEST_LDFLAGS= --pre-js build/make/test-pre.js -lnodefs.js
|
||||||
|
|
||||||
DYNLINK=0
|
DYNLINK=0
|
||||||
SHARED_LIB=1
|
SHARED_LIB=1
|
||||||
|
@ -106,6 +98,7 @@ STATIC_LIB=0
|
||||||
EXAMPLES=1
|
EXAMPLES=1
|
||||||
OPENMPT123=0
|
OPENMPT123=0
|
||||||
SHARED_SONAME=0
|
SHARED_SONAME=0
|
||||||
|
NO_SHARED_LINKER_FLAG=1
|
||||||
|
|
||||||
# Disable the generic compiler optimization flags as emscripten is sufficiently different.
|
# Disable the generic compiler optimization flags as emscripten is sufficiently different.
|
||||||
# Optimization flags are hard-coded for emscripten in this file.
|
# Optimization flags are hard-coded for emscripten in this file.
|
||||||
|
|
|
@ -9,14 +9,6 @@ CXXFLAGS_STDCXX = -std=$(STDCXX)
|
||||||
else
|
else
|
||||||
ifeq ($(shell printf '\n' > bin/empty.cpp ; if $(CXX) -std=c++17 -c bin/empty.cpp -o bin/empty.out > /dev/null 2>&1 ; then echo 'c++17' ; fi ), c++17)
|
ifeq ($(shell printf '\n' > bin/empty.cpp ; if $(CXX) -std=c++17 -c bin/empty.cpp -o bin/empty.out > /dev/null 2>&1 ; then echo 'c++17' ; fi ), c++17)
|
||||||
CXXFLAGS_STDCXX = -std=c++17
|
CXXFLAGS_STDCXX = -std=c++17
|
||||||
else
|
|
||||||
ifeq ($(shell printf '\n' > bin/empty.cpp ; if $(CXX) -std=c++14 -c bin/empty.cpp -o bin/empty.out > /dev/null 2>&1 ; then echo 'c++14' ; fi ), c++14)
|
|
||||||
CXXFLAGS_STDCXX = -std=c++14
|
|
||||||
else
|
|
||||||
ifeq ($(shell printf '\n' > bin/empty.cpp ; if $(CXX) -std=c++11 -c bin/empty.cpp -o bin/empty.out > /dev/null 2>&1 ; then echo 'c++11' ; fi ), c++11)
|
|
||||||
CXXFLAGS_STDCXX = -std=c++11
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
CFLAGS_STDC = -std=c99
|
CFLAGS_STDC = -std=c99
|
||||||
|
@ -40,17 +32,27 @@ CXXFLAGS += -fsanitize=undefined
|
||||||
CFLAGS += -fsanitize=undefined
|
CFLAGS += -fsanitize=undefined
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
CXXFLAGS_WARNINGS += -Wsuggest-override -Wno-psabi
|
||||||
|
|
||||||
ifeq ($(MODERN),1)
|
ifeq ($(MODERN),1)
|
||||||
LDFLAGS += -fuse-ld=gold
|
LDFLAGS += -fuse-ld=gold
|
||||||
CXXFLAGS_WARNINGS += -Wpedantic -Wlogical-op -Wframe-larger-than=16000
|
CXXFLAGS_WARNINGS += -Wpedantic -Wlogical-op -Wframe-larger-than=16000
|
||||||
#CXXFLAGS_WARNINGS += -Wdouble-promotion
|
|
||||||
CFLAGS_WARNINGS += -Wpedantic -Wlogical-op -Wframe-larger-than=4000
|
CFLAGS_WARNINGS += -Wpedantic -Wlogical-op -Wframe-larger-than=4000
|
||||||
#CFLAGS_WARNINGS += -Wdouble-promotion
|
|
||||||
LDFLAGS_WARNINGS += -Wl,-no-undefined -Wl,--detect-odr-violations
|
LDFLAGS_WARNINGS += -Wl,-no-undefined -Wl,--detect-odr-violations
|
||||||
CXXFLAGS_WARNINGS += -Wsuggest-override
|
# re-renable after 1.29 branch
|
||||||
|
#CXXFLAGS_WARNINGS += -Wdouble-promotion
|
||||||
|
#CFLAGS_WARNINGS += -Wdouble-promotion
|
||||||
endif
|
endif
|
||||||
|
|
||||||
CFLAGS_SILENT += -Wno-unused-parameter -Wno-unused-function -Wno-cast-qual -Wno-old-style-declaration -Wno-type-limits -Wno-unused-but-set-variable
|
CFLAGS_SILENT += -Wno-cast-qual
|
||||||
|
CFLAGS_SILENT += -Wno-empty-body
|
||||||
|
CFLAGS_SILENT += -Wno-implicit-fallthrough
|
||||||
|
CFLAGS_SILENT += -Wno-old-style-declaration
|
||||||
|
CFLAGS_SILENT += -Wno-sign-compare
|
||||||
|
CFLAGS_SILENT += -Wno-type-limits
|
||||||
|
CFLAGS_SILENT += -Wno-unused-but-set-variable
|
||||||
|
CFLAGS_SILENT += -Wno-unused-function
|
||||||
|
CFLAGS_SILENT += -Wno-unused-parameter
|
||||||
|
|
||||||
EXESUFFIX=
|
EXESUFFIX=
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ CXX ?= c++
|
||||||
LD ?= c++
|
LD ?= c++
|
||||||
AR = ar
|
AR = ar
|
||||||
|
|
||||||
CXXFLAGS_STDCXX = -std=c++11
|
CXXFLAGS_STDCXX = -std=c++17
|
||||||
CFLAGS_STDC = -std=c99
|
CFLAGS_STDC = -std=c99
|
||||||
CXXFLAGS += $(CXXFLAGS_STDCXX)
|
CXXFLAGS += $(CXXFLAGS_STDCXX)
|
||||||
CFLAGS += $(CFLAGS_STDC)
|
CFLAGS += $(CFLAGS_STDC)
|
||||||
|
|
|
@ -4,7 +4,7 @@ CXX = i686-w64-mingw32-g++$(MINGW_FLAVOUR)
|
||||||
LD = i686-w64-mingw32-g++$(MINGW_FLAVOUR)
|
LD = i686-w64-mingw32-g++$(MINGW_FLAVOUR)
|
||||||
AR = i686-w64-mingw32-ar$(MINGW_FLAVOUR)
|
AR = i686-w64-mingw32-ar$(MINGW_FLAVOUR)
|
||||||
|
|
||||||
CXXFLAGS_STDCXX = -std=c++11
|
CXXFLAGS_STDCXX = -std=c++17
|
||||||
CFLAGS_STDC = -std=c99
|
CFLAGS_STDC = -std=c99
|
||||||
CXXFLAGS += $(CXXFLAGS_STDCXX)
|
CXXFLAGS += $(CXXFLAGS_STDCXX)
|
||||||
CFLAGS += $(CFLAGS_STDC)
|
CFLAGS += $(CFLAGS_STDC)
|
||||||
|
|
|
@ -4,7 +4,7 @@ CXX = x86_64-w64-mingw32-g++$(MINGW_FLAVOUR)
|
||||||
LD = x86_64-w64-mingw32-g++$(MINGW_FLAVOUR)
|
LD = x86_64-w64-mingw32-g++$(MINGW_FLAVOUR)
|
||||||
AR = x86_64-w64-mingw32-ar$(MINGW_FLAVOUR)
|
AR = x86_64-w64-mingw32-ar$(MINGW_FLAVOUR)
|
||||||
|
|
||||||
CXXFLAGS_STDCXX = -std=c++11
|
CXXFLAGS_STDCXX = -std=c++17
|
||||||
CFLAGS_STDC = -std=c99
|
CFLAGS_STDC = -std=c99
|
||||||
CXXFLAGS += $(CXXFLAGS_STDCXX)
|
CXXFLAGS += $(CXXFLAGS_STDCXX)
|
||||||
CFLAGS += $(CFLAGS_STDC)
|
CFLAGS += $(CFLAGS_STDC)
|
||||||
|
|
|
@ -4,7 +4,7 @@ CXX = x86_64-w64-mingw32-g++$(MINGW_FLAVOUR)
|
||||||
LD = x86_64-w64-mingw32-g++$(MINGW_FLAVOUR)
|
LD = x86_64-w64-mingw32-g++$(MINGW_FLAVOUR)
|
||||||
AR = x86_64-w64-mingw32-ar$(MINGW_FLAVOUR)
|
AR = x86_64-w64-mingw32-ar$(MINGW_FLAVOUR)
|
||||||
|
|
||||||
CXXFLAGS_STDCXX = -std=c++11
|
CXXFLAGS_STDCXX = -std=c++17
|
||||||
CFLAGS_STDC = -std=c99
|
CFLAGS_STDC = -std=c99
|
||||||
CXXFLAGS += $(CXXFLAGS_STDCXX)
|
CXXFLAGS += $(CXXFLAGS_STDCXX)
|
||||||
CFLAGS += $(CFLAGS_STDC)
|
CFLAGS += $(CFLAGS_STDC)
|
||||||
|
|
|
@ -4,7 +4,7 @@ CXX = i686-w64-mingw32-g++$(MINGW_FLAVOUR)
|
||||||
LD = i686-w64-mingw32-g++$(MINGW_FLAVOUR)
|
LD = i686-w64-mingw32-g++$(MINGW_FLAVOUR)
|
||||||
AR = i686-w64-mingw32-ar$(MINGW_FLAVOUR)
|
AR = i686-w64-mingw32-ar$(MINGW_FLAVOUR)
|
||||||
|
|
||||||
CXXFLAGS_STDCXX = -std=c++11
|
CXXFLAGS_STDCXX = -std=c++17
|
||||||
CFLAGS_STDC = -std=c99
|
CFLAGS_STDC = -std=c99
|
||||||
CXXFLAGS += $(CXXFLAGS_STDCXX)
|
CXXFLAGS += $(CXXFLAGS_STDCXX)
|
||||||
CFLAGS += $(CFLAGS_STDC)
|
CFLAGS += $(CFLAGS_STDC)
|
||||||
|
|
|
@ -4,7 +4,7 @@ CXX ?= c++
|
||||||
LD ?= c++
|
LD ?= c++
|
||||||
AR = ar
|
AR = ar
|
||||||
|
|
||||||
CXXFLAGS_STDCXX = -std=c++11
|
CXXFLAGS_STDCXX = -std=c++17
|
||||||
CFLAGS_STDC = -std=c99
|
CFLAGS_STDC = -std=c99
|
||||||
CXXFLAGS += $(CXXFLAGS_STDCXX)
|
CXXFLAGS += $(CXXFLAGS_STDCXX)
|
||||||
CFLAGS += $(CFLAGS_STDC)
|
CFLAGS += $(CFLAGS_STDC)
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#define OPENMPT_VERSION_SVNVERSION "12263"
|
#define OPENMPT_VERSION_SVNVERSION "13555"
|
||||||
#define OPENMPT_VERSION_REVISION 12263
|
#define OPENMPT_VERSION_REVISION 13555
|
||||||
#define OPENMPT_VERSION_DIRTY 0
|
#define OPENMPT_VERSION_DIRTY 0
|
||||||
#define OPENMPT_VERSION_MIXEDREVISIONS 0
|
#define OPENMPT_VERSION_MIXEDREVISIONS 0
|
||||||
#define OPENMPT_VERSION_URL "https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.4.10"
|
#define OPENMPT_VERSION_URL "https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.5.2"
|
||||||
#define OPENMPT_VERSION_DATE "2019-10-30T10:43:15.521271Z"
|
#define OPENMPT_VERSION_DATE "2020-08-30T13:42:32.941871Z"
|
||||||
#define OPENMPT_VERSION_IS_PACKAGE 1
|
#define OPENMPT_VERSION_IS_PACKAGE 1
|
||||||
|
|
||||||
|
|
|
@ -20,36 +20,10 @@
|
||||||
|
|
||||||
#if MPT_OS_WINDOWS
|
#if MPT_OS_WINDOWS
|
||||||
|
|
||||||
#if defined(MPT_BUILD_MSVC)
|
|
||||||
|
|
||||||
#if defined(MPT_BUILD_TARGET_XP)
|
|
||||||
|
|
||||||
#if defined(_M_X64)
|
|
||||||
#ifndef _WIN32_WINNT
|
|
||||||
#define _WIN32_WINNT 0x0502 // _WIN32_WINNT_WS03
|
|
||||||
#endif
|
|
||||||
#else // !_M_X64
|
|
||||||
#ifndef _WIN32_WINNT
|
|
||||||
#define _WIN32_WINNT 0x0501 // _WIN32_WINNT_WINXP
|
|
||||||
#endif
|
|
||||||
#endif // _M_X64
|
|
||||||
|
|
||||||
#else // MPT_BUILD_TARGET
|
|
||||||
|
|
||||||
#ifndef _WIN32_WINNT
|
#ifndef _WIN32_WINNT
|
||||||
#define _WIN32_WINNT 0x0601 // _WIN32_WINNT_WIN7
|
#define _WIN32_WINNT 0x0601 // _WIN32_WINNT_WIN7
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // MPT_BUILD_TARGET
|
|
||||||
|
|
||||||
#else // !MPT_BUILD_MSVC
|
|
||||||
|
|
||||||
#ifndef _WIN32_WINNT
|
|
||||||
#define _WIN32_WINNT 0x0501 // _WIN32_WINNT_WINXP
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // MPT_BUILD_MSVC
|
|
||||||
|
|
||||||
#ifndef WINVER
|
#ifndef WINVER
|
||||||
#define WINVER _WIN32_WINNT
|
#define WINVER _WIN32_WINNT
|
||||||
#endif
|
#endif
|
||||||
|
@ -98,8 +72,15 @@
|
||||||
|
|
||||||
#if defined(MODPLUG_TRACKER)
|
#if defined(MODPLUG_TRACKER)
|
||||||
|
|
||||||
|
#if MPT_OS_WINDOWS
|
||||||
|
#if !defined(MPT_BUILD_WINESUPPORT)
|
||||||
|
#define MPT_WITH_MFC
|
||||||
|
#endif // !MPT_BUILD_WINESUPPORT
|
||||||
|
#endif // MPT_OS_WINDOWS
|
||||||
|
|
||||||
// OpenMPT-only dependencies
|
// OpenMPT-only dependencies
|
||||||
#define MPT_WITH_ASIO
|
#define MPT_WITH_ASIO
|
||||||
|
#define MPT_WITH_DMO
|
||||||
#define MPT_WITH_LAME
|
#define MPT_WITH_LAME
|
||||||
#define MPT_WITH_LHASA
|
#define MPT_WITH_LHASA
|
||||||
#define MPT_WITH_MINIZIP
|
#define MPT_WITH_MINIZIP
|
||||||
|
@ -118,13 +99,10 @@
|
||||||
// OpenMPT and libopenmpt dependencies (not for openmp123, player plugins or examples)
|
// OpenMPT and libopenmpt dependencies (not for openmp123, player plugins or examples)
|
||||||
//#define MPT_WITH_DL
|
//#define MPT_WITH_DL
|
||||||
#define MPT_WITH_FLAC
|
#define MPT_WITH_FLAC
|
||||||
//#define MPT_WITH_ICONV
|
|
||||||
//#define MPT_WITH_LTDL
|
//#define MPT_WITH_LTDL
|
||||||
#if MPT_OS_WINDOWS
|
#if MPT_OS_WINDOWS
|
||||||
#if (_WIN32_WINNT >= 0x0601)
|
|
||||||
#define MPT_WITH_MEDIAFOUNDATION
|
#define MPT_WITH_MEDIAFOUNDATION
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
//#define MPT_WITH_MINIMP3
|
//#define MPT_WITH_MINIMP3
|
||||||
//#define MPT_WITH_MINIZ
|
//#define MPT_WITH_MINIZ
|
||||||
#define MPT_WITH_MPG123
|
#define MPT_WITH_MPG123
|
||||||
|
@ -132,6 +110,11 @@
|
||||||
//#define MPT_WITH_STBVORBIS
|
//#define MPT_WITH_STBVORBIS
|
||||||
#define MPT_WITH_VORBIS
|
#define MPT_WITH_VORBIS
|
||||||
#define MPT_WITH_VORBISFILE
|
#define MPT_WITH_VORBISFILE
|
||||||
|
#if MPT_OS_WINDOWS
|
||||||
|
#if (_WIN32_WINNT >= 0x0A00)
|
||||||
|
#define MPT_WITH_WINDOWS10
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
#define MPT_WITH_ZLIB
|
#define MPT_WITH_ZLIB
|
||||||
|
|
||||||
#endif // MODPLUG_TRACKER
|
#endif // MODPLUG_TRACKER
|
||||||
|
@ -147,7 +130,6 @@
|
||||||
|
|
||||||
//#define MPT_WITH_DL
|
//#define MPT_WITH_DL
|
||||||
//#define MPT_WITH_FLAC
|
//#define MPT_WITH_FLAC
|
||||||
//#define MPT_WITH_ICONV
|
|
||||||
//#define MPT_WITH_LTDL
|
//#define MPT_WITH_LTDL
|
||||||
//#define MPT_WITH_MEDIAFOUNDATION
|
//#define MPT_WITH_MEDIAFOUNDATION
|
||||||
#define MPT_WITH_MINIMP3
|
#define MPT_WITH_MINIMP3
|
||||||
|
@ -163,7 +145,6 @@
|
||||||
|
|
||||||
//#define MPT_WITH_DL
|
//#define MPT_WITH_DL
|
||||||
//#define MPT_WITH_FLAC
|
//#define MPT_WITH_FLAC
|
||||||
//#define MPT_WITH_ICONV
|
|
||||||
//#define MPT_WITH_LTDL
|
//#define MPT_WITH_LTDL
|
||||||
//#define MPT_WITH_MEDIAFOUNDATION
|
//#define MPT_WITH_MEDIAFOUNDATION
|
||||||
//#define MPT_WITH_MINIMP3
|
//#define MPT_WITH_MINIMP3
|
||||||
|
@ -194,7 +175,6 @@
|
||||||
|
|
||||||
//#define MPT_WITH_DL
|
//#define MPT_WITH_DL
|
||||||
//#define MPT_WITH_FLAC
|
//#define MPT_WITH_FLAC
|
||||||
//#define MPT_WITH_ICONV
|
|
||||||
//#define MPT_WITH_LTDL
|
//#define MPT_WITH_LTDL
|
||||||
//#define MPT_WITH_MEDIAFOUNDATION
|
//#define MPT_WITH_MEDIAFOUNDATION
|
||||||
//#define MPT_WITH_MINIMP3
|
//#define MPT_WITH_MINIMP3
|
||||||
|
@ -229,14 +209,14 @@
|
||||||
#define MPT_LOG_GLOBAL_LEVEL 0
|
#define MPT_LOG_GLOBAL_LEVEL 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Enable all individual logging macros and MPT_LOG calls
|
||||||
|
//#define MPT_ALL_LOGGING
|
||||||
|
|
||||||
// Disable all runtime asserts
|
// Disable all runtime asserts
|
||||||
#if !defined(MPT_BUILD_DEBUG) && !defined(MPT_BUILD_CHECKED) && !defined(MPT_BUILD_WINESUPPORT)
|
#if !defined(MPT_BUILD_DEBUG) && !defined(MPT_BUILD_CHECKED) && !defined(MPT_BUILD_WINESUPPORT)
|
||||||
#define NO_ASSERTS
|
#define NO_ASSERTS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Enable std::istream support in class FileReader (this is generally not needed for the tracker, local files can easily be mmapped as they have been before introducing std::istream support)
|
|
||||||
//#define MPT_FILEREADER_STD_ISTREAM
|
|
||||||
|
|
||||||
// Enable callback stream wrapper for FileReader (required by libopenmpt C API).
|
// Enable callback stream wrapper for FileReader (required by libopenmpt C API).
|
||||||
//#define MPT_FILEREADER_CALLBACK_STREAM
|
//#define MPT_FILEREADER_CALLBACK_STREAM
|
||||||
|
|
||||||
|
@ -267,9 +247,6 @@
|
||||||
// Define to build without VST plugin support; makes build possible without VST SDK.
|
// Define to build without VST plugin support; makes build possible without VST SDK.
|
||||||
//#define NO_VST
|
//#define NO_VST
|
||||||
|
|
||||||
// Define to build without DMO plugin support
|
|
||||||
//#define NO_DMO
|
|
||||||
|
|
||||||
// (HACK) Define to build without any plugin support
|
// (HACK) Define to build without any plugin support
|
||||||
//#define NO_PLUGINS
|
//#define NO_PLUGINS
|
||||||
|
|
||||||
|
@ -300,7 +277,7 @@
|
||||||
#define NO_ASSERTS
|
#define NO_ASSERTS
|
||||||
#endif
|
#endif
|
||||||
//#define NO_LOGGING
|
//#define NO_LOGGING
|
||||||
#define MPT_FILEREADER_STD_ISTREAM
|
//#define MPT_ALL_LOGGING
|
||||||
#define MPT_FILEREADER_CALLBACK_STREAM
|
#define MPT_FILEREADER_CALLBACK_STREAM
|
||||||
//#define MPT_EXTERNAL_SAMPLES
|
//#define MPT_EXTERNAL_SAMPLES
|
||||||
#if defined(ENABLE_TESTS) || defined(MPT_BUILD_HACK_ARCHIVE_SUPPORT)
|
#if defined(ENABLE_TESTS) || defined(MPT_BUILD_HACK_ARCHIVE_SUPPORT)
|
||||||
|
@ -320,9 +297,6 @@
|
||||||
#define NO_EQ
|
#define NO_EQ
|
||||||
#define NO_AGC
|
#define NO_AGC
|
||||||
#define NO_VST
|
#define NO_VST
|
||||||
//#if !MPT_OS_WINDOWS || MPT_OS_WINDOWS_WINRT || !MPT_COMPILER_MSVC || !defined(LIBOPENMPT_BUILD_FULL)
|
|
||||||
#define NO_DMO
|
|
||||||
//#endif
|
|
||||||
//#define NO_PLUGINS
|
//#define NO_PLUGINS
|
||||||
//#define NO_LIBOPENMPT_C
|
//#define NO_LIBOPENMPT_C
|
||||||
//#define NO_LIBOPENMPT_CXX
|
//#define NO_LIBOPENMPT_CXX
|
||||||
|
@ -333,51 +307,28 @@
|
||||||
|
|
||||||
#if MPT_OS_WINDOWS
|
#if MPT_OS_WINDOWS
|
||||||
|
|
||||||
#define MPT_CHARSET_WIN32
|
|
||||||
#ifndef MPT_ENABLE_CHARSET_LOCALE
|
#ifndef MPT_ENABLE_CHARSET_LOCALE
|
||||||
#define MPT_ENABLE_CHARSET_LOCALE
|
#define MPT_ENABLE_CHARSET_LOCALE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#elif MPT_OS_LINUX
|
#elif MPT_OS_LINUX
|
||||||
|
|
||||||
#define MPT_CHARSET_ICONV
|
|
||||||
|
|
||||||
#elif MPT_OS_ANDROID
|
#elif MPT_OS_ANDROID
|
||||||
|
|
||||||
#define MPT_CHARSET_INTERNAL
|
|
||||||
|
|
||||||
#elif MPT_OS_EMSCRIPTEN
|
#elif MPT_OS_EMSCRIPTEN
|
||||||
|
|
||||||
#define MPT_CHARSET_INTERNAL
|
|
||||||
#ifndef MPT_LOCALE_ASSUME_CHARSET
|
#ifndef MPT_LOCALE_ASSUME_CHARSET
|
||||||
#define MPT_LOCALE_ASSUME_CHARSET CharsetUTF8
|
#define MPT_LOCALE_ASSUME_CHARSET Charset::UTF8
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#elif MPT_OS_MACOSX_OR_IOS
|
#elif MPT_OS_MACOSX_OR_IOS
|
||||||
|
|
||||||
#if defined(MPT_WITH_ICONV)
|
|
||||||
#define MPT_CHARSET_ICONV
|
|
||||||
#ifndef MPT_ICONV_NO_WCHAR
|
|
||||||
#define MPT_ICONV_NO_WCHAR
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#define MPT_CHARSET_INTERNAL
|
|
||||||
#endif
|
|
||||||
//#ifndef MPT_LOCALE_ASSUME_CHARSET
|
|
||||||
//#define MPT_LOCALE_ASSUME_CHARSET CharsetUTF8
|
|
||||||
//#endif
|
|
||||||
|
|
||||||
#elif MPT_OS_DJGPP
|
#elif MPT_OS_DJGPP
|
||||||
|
|
||||||
#define MPT_CHARSET_INTERNAL
|
|
||||||
#ifndef MPT_LOCALE_ASSUME_CHARSET
|
#ifndef MPT_LOCALE_ASSUME_CHARSET
|
||||||
#define MPT_LOCALE_ASSUME_CHARSET CharsetCP437
|
#define MPT_LOCALE_ASSUME_CHARSET Charset::CP437
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#elif defined(MPT_WITH_ICONV)
|
|
||||||
|
|
||||||
#define MPT_CHARSET_ICONV
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -457,6 +408,7 @@
|
||||||
#if defined(ENABLE_ASM)
|
#if defined(ENABLE_ASM)
|
||||||
#if MPT_COMPILER_MSVC && defined(_M_IX86)
|
#if MPT_COMPILER_MSVC && defined(_M_IX86)
|
||||||
|
|
||||||
|
#define ENABLE_CPUID
|
||||||
// Generate general x86 inline assembly and intrinsics.
|
// Generate general x86 inline assembly and intrinsics.
|
||||||
#define ENABLE_X86
|
#define ENABLE_X86
|
||||||
// Generate MMX instructions (only used when the CPU supports it).
|
// Generate MMX instructions (only used when the CPU supports it).
|
||||||
|
@ -469,14 +421,14 @@
|
||||||
#define ENABLE_SSE3
|
#define ENABLE_SSE3
|
||||||
// Generate SSE4 instructions (only used when the CPU supports it).
|
// Generate SSE4 instructions (only used when the CPU supports it).
|
||||||
#define ENABLE_SSE4
|
#define ENABLE_SSE4
|
||||||
|
// Generate AVX instructions (only used when the CPU supports it).
|
||||||
#if defined(MPT_BUILD_TARGET_XP)
|
#define ENABLE_AVX
|
||||||
// Generate AMD specific instruction set extensions (only used when the CPU supports it).
|
// Generate AVX2 instructions (only used when the CPU supports it).
|
||||||
#define ENABLE_X86_AMD
|
#define ENABLE_AVX2
|
||||||
#endif
|
|
||||||
|
|
||||||
#elif MPT_COMPILER_MSVC && defined(_M_X64)
|
#elif MPT_COMPILER_MSVC && defined(_M_X64)
|
||||||
|
|
||||||
|
#define ENABLE_CPUID
|
||||||
// Generate general x64 intrinsics.
|
// Generate general x64 intrinsics.
|
||||||
#define ENABLE_X64
|
#define ENABLE_X64
|
||||||
// Generate SSE instructions (only used when the CPU supports it).
|
// Generate SSE instructions (only used when the CPU supports it).
|
||||||
|
@ -487,18 +439,14 @@
|
||||||
#define ENABLE_SSE3
|
#define ENABLE_SSE3
|
||||||
// Generate SSE4 instructions (only used when the CPU supports it).
|
// Generate SSE4 instructions (only used when the CPU supports it).
|
||||||
#define ENABLE_SSE4
|
#define ENABLE_SSE4
|
||||||
|
// Generate AVX instructions (only used when the CPU supports it).
|
||||||
|
#define ENABLE_AVX
|
||||||
|
// Generate AVX2 instructions (only used when the CPU supports it).
|
||||||
|
#define ENABLE_AVX2
|
||||||
|
|
||||||
#endif // arch
|
#endif // arch
|
||||||
#endif // ENABLE_ASM
|
#endif // ENABLE_ASM
|
||||||
|
|
||||||
#if defined(MPT_WITH_LAME) && defined(MPT_BUILD_MSVC) && defined(MPT_BUILD_MSVC_STATIC) && defined(MODPLUG_TRACKER) && !MPT_OS_WINDOWS_WINRT
|
|
||||||
#define MPT_ENABLE_LAME_DELAYLOAD
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MPT_WITH_MPG123) && defined(MPT_BUILD_MSVC) && defined(MPT_BUILD_MSVC_STATIC) && defined(MODPLUG_TRACKER) && !MPT_OS_WINDOWS_WINRT
|
|
||||||
#define MPT_ENABLE_MPG123_DELAYLOAD
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ENABLE_TESTS) && defined(MODPLUG_NO_FILESAVE)
|
#if defined(ENABLE_TESTS) && defined(MODPLUG_NO_FILESAVE)
|
||||||
#undef MODPLUG_NO_FILESAVE // tests recommend file saving
|
#undef MODPLUG_NO_FILESAVE // tests recommend file saving
|
||||||
#endif
|
#endif
|
||||||
|
@ -524,26 +472,10 @@
|
||||||
#define MPT_ENABLE_TEMPFILE
|
#define MPT_ENABLE_TEMPFILE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MPT_CXX_AT_LEAST(17) && defined(MPT_CHARSET_CODECVTUTF8)
|
|
||||||
#undef MPT_CHARSET_CODECVTUTF8 // std::codecvt_utf8 is deprecated in c++17
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(MPT_CHARSET_WIN32) && !defined(MPT_CHARSET_ICONV) && !defined(MPT_CHARSET_CODECVTUTF8) && !defined(MPT_CHARSET_INTERNAL)
|
|
||||||
#define MPT_CHARSET_INTERNAL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODPLUG_TRACKER) && !defined(MPT_ENABLE_DYNBIND)
|
#if defined(MODPLUG_TRACKER) && !defined(MPT_ENABLE_DYNBIND)
|
||||||
#define MPT_ENABLE_DYNBIND // Tracker requires dynamic library loading for export codecs
|
#define MPT_ENABLE_DYNBIND // Tracker requires dynamic library loading for export codecs
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(MPT_ENABLE_LAME_DELAYLOAD) && !defined(MPT_ENABLE_DYNBIND)
|
|
||||||
#define MPT_ENABLE_DYNBIND // static MSVC builds require dynbind to load delay-loaded DLLs
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MPT_ENABLE_MPG123_DELAYLOAD) && !defined(MPT_ENABLE_DYNBIND)
|
|
||||||
#define MPT_ENABLE_DYNBIND // static MSVC builds require dynbind to load delay-loaded DLLs
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MPT_WITH_MEDIAFOUNDATION) && !defined(MPT_ENABLE_DYNBIND)
|
#if defined(MPT_WITH_MEDIAFOUNDATION) && !defined(MPT_ENABLE_DYNBIND)
|
||||||
#define MPT_ENABLE_DYNBIND // MediaFoundation needs dynamic loading in order to test availability of delay loaded libs
|
#define MPT_ENABLE_DYNBIND // MediaFoundation needs dynamic loading in order to test availability of delay loaded libs
|
||||||
#endif
|
#endif
|
||||||
|
@ -556,10 +488,6 @@
|
||||||
#define MPT_ENABLE_FILEIO // Test suite requires PathString for file loading.
|
#define MPT_ENABLE_FILEIO // Test suite requires PathString for file loading.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !MPT_OS_WINDOWS && !defined(MPT_FILEREADER_STD_ISTREAM)
|
|
||||||
#define MPT_FILEREADER_STD_ISTREAM // MMAP is only supported on Windows
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODPLUG_TRACKER) && !defined(MPT_ENABLE_FILEIO)
|
#if defined(MODPLUG_TRACKER) && !defined(MPT_ENABLE_FILEIO)
|
||||||
#define MPT_ENABLE_FILEIO // Tracker requires disk file io
|
#define MPT_ENABLE_FILEIO // Tracker requires disk file io
|
||||||
#endif
|
#endif
|
||||||
|
@ -575,7 +503,6 @@
|
||||||
#if defined(NO_PLUGINS)
|
#if defined(NO_PLUGINS)
|
||||||
// Any plugin type requires NO_PLUGINS to not be defined.
|
// Any plugin type requires NO_PLUGINS to not be defined.
|
||||||
#define NO_VST
|
#define NO_VST
|
||||||
#define NO_DMO
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(ENABLE_ASM) || !defined(NO_VST)
|
#if defined(ENABLE_ASM) || !defined(NO_VST)
|
||||||
|
@ -626,6 +553,10 @@
|
||||||
|
|
||||||
// platform configuration
|
// platform configuration
|
||||||
|
|
||||||
|
#ifdef MPT_WITH_MFC
|
||||||
|
//#define MPT_MFC_FULL // use full MFC, including MFC controls
|
||||||
|
#endif // MPT_WITH_MFC
|
||||||
|
|
||||||
#if defined(MODPLUG_TRACKER)
|
#if defined(MODPLUG_TRACKER)
|
||||||
#if MPT_OS_WINDOWS
|
#if MPT_OS_WINDOWS
|
||||||
#if !defined(MPT_BUILD_WINESUPPORT)
|
#if !defined(MPT_BUILD_WINESUPPORT)
|
||||||
|
@ -721,11 +652,13 @@
|
||||||
#pragma warning(disable:4512) // assignment operator could not be generated
|
#pragma warning(disable:4512) // assignment operator could not be generated
|
||||||
|
|
||||||
#pragma warning(error:4309) // Treat "truncation of constant value"-warning as error.
|
#pragma warning(error:4309) // Treat "truncation of constant value"-warning as error.
|
||||||
|
#pragma warning(error:4463) // Treat overflow; assigning value to bit-field that can only hold values from low_value to high_value"-warning as error.
|
||||||
|
|
||||||
#ifdef MPT_BUILD_ANALYZED
|
#ifdef MPT_BUILD_ANALYZED
|
||||||
// Disable Visual Studio static analyzer warnings that generate too many false positives in VS2010.
|
// Disable Visual Studio static analyzer warnings that generate too many false positives in VS2010.
|
||||||
//#pragma warning(disable:6246)
|
//#pragma warning(disable:6246)
|
||||||
//#pragma warning(disable:6262)
|
//#pragma warning(disable:6262)
|
||||||
|
#pragma warning(disable:6297) // 32-bit value is shifted, then cast to 64-bit value. Results might not be an expected value.
|
||||||
#pragma warning(disable:6326) // Potential comparison of a constant with another constant
|
#pragma warning(disable:6326) // Potential comparison of a constant with another constant
|
||||||
//#pragma warning(disable:6385)
|
//#pragma warning(disable:6385)
|
||||||
//#pragma warning(disable:6386)
|
//#pragma warning(disable:6386)
|
||||||
|
@ -733,32 +666,30 @@
|
||||||
|
|
||||||
#endif // MPT_COMPILER_MSVC
|
#endif // MPT_COMPILER_MSVC
|
||||||
|
|
||||||
|
#if MPT_COMPILER_CLANG
|
||||||
|
|
||||||
|
#if defined(MPT_BUILD_MSVC)
|
||||||
|
#pragma clang diagnostic warning "-Wimplicit-fallthrough"
|
||||||
|
#endif // MPT_BUILD_MSVC
|
||||||
|
|
||||||
|
#if defined(MODPLUG_TRACKER)
|
||||||
|
#pragma clang diagnostic ignored "-Wunused-local-typedef"
|
||||||
|
#endif // MODPLUG_TRACKER
|
||||||
|
|
||||||
|
#endif // MPT_COMPILER_CLANG
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// standard library quirks
|
// standard library quirks
|
||||||
|
|
||||||
#if MPT_CXX_AT_LEAST(17)
|
|
||||||
#if (MPT_COMPILER_GCC || MPT_COMPILER_CLANG)
|
|
||||||
// we need to detect the standard library via macro __GLIBCXX__
|
|
||||||
#include <vector>
|
|
||||||
#endif
|
|
||||||
#if MPT_COMPILER_MSVC || MPT_GCC_BEFORE(8,1,0) || MPT_CLANG_BEFORE(5,0,0) || (MPT_COMPILER_GCC && defined(__GLIBCXX__) && (defined(__MINGW32__) || defined(__MINGW64__))) || (MPT_COMPILER_CLANG && defined(__GLIBCXX__)) || (MPT_COMPILER_CLANG && MPT_OS_MACOSX_OR_IOS) || MPT_OS_OPENBSD || MPT_OS_EMSCRIPTEN || MPT_OS_HAIKU || (defined(__clang__) && defined(_MSC_VER))
|
|
||||||
#define MPT_COMPILER_QUIRK_NO_ALIGNEDALLOC
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// third-party library configuration
|
// third-party library configuration
|
||||||
|
|
||||||
#if defined(MODPLUG_TRACKER)
|
|
||||||
//#define MPT_MFC_FULL // use full MFC, including MFC controls
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MPT_WITH_FLAC
|
#ifdef MPT_WITH_FLAC
|
||||||
#ifdef MPT_BUILD_MSVC_STATIC
|
#ifdef MPT_BUILD_MSVC_STATIC
|
||||||
#define FLAC__NO_DLL
|
#define FLAC__NO_DLL
|
||||||
|
|
|
@ -34,8 +34,8 @@
|
||||||
#define MPT_CLANG_AT_LEAST(major,minor,patch) (MPT_COMPILER_CLANG_VERSION >= MPT_COMPILER_MAKE_VERSION3((major),(minor),(patch)))
|
#define MPT_CLANG_AT_LEAST(major,minor,patch) (MPT_COMPILER_CLANG_VERSION >= MPT_COMPILER_MAKE_VERSION3((major),(minor),(patch)))
|
||||||
#define MPT_CLANG_BEFORE(major,minor,patch) (MPT_COMPILER_CLANG_VERSION < MPT_COMPILER_MAKE_VERSION3((major),(minor),(patch)))
|
#define MPT_CLANG_BEFORE(major,minor,patch) (MPT_COMPILER_CLANG_VERSION < MPT_COMPILER_MAKE_VERSION3((major),(minor),(patch)))
|
||||||
|
|
||||||
#if MPT_CLANG_BEFORE(3,6,0)
|
#if MPT_CLANG_BEFORE(5,0,0)
|
||||||
#error "clang version 3.6 required"
|
#error "clang version 5 required"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__clang_analyzer__)
|
#if defined(__clang_analyzer__)
|
||||||
|
@ -51,14 +51,22 @@
|
||||||
#define MPT_GCC_AT_LEAST(major,minor,patch) (MPT_COMPILER_GCC_VERSION >= MPT_COMPILER_MAKE_VERSION3((major),(minor),(patch)))
|
#define MPT_GCC_AT_LEAST(major,minor,patch) (MPT_COMPILER_GCC_VERSION >= MPT_COMPILER_MAKE_VERSION3((major),(minor),(patch)))
|
||||||
#define MPT_GCC_BEFORE(major,minor,patch) (MPT_COMPILER_GCC_VERSION < MPT_COMPILER_MAKE_VERSION3((major),(minor),(patch)))
|
#define MPT_GCC_BEFORE(major,minor,patch) (MPT_COMPILER_GCC_VERSION < MPT_COMPILER_MAKE_VERSION3((major),(minor),(patch)))
|
||||||
|
|
||||||
#if MPT_GCC_BEFORE(4,8,0)
|
#if MPT_GCC_BEFORE(7,1,0)
|
||||||
#error "GCC version 4.8 required"
|
#error "GCC version 7.1 required"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER)
|
||||||
|
|
||||||
#define MPT_COMPILER_MSVC 1
|
#define MPT_COMPILER_MSVC 1
|
||||||
#if (_MSC_VER >= 1922)
|
#if (_MSC_VER >= 1926)
|
||||||
|
#define MPT_COMPILER_MSVC_VERSION MPT_COMPILER_MAKE_VERSION2(2019,6)
|
||||||
|
#elif (_MSC_VER >= 1925)
|
||||||
|
#define MPT_COMPILER_MSVC_VERSION MPT_COMPILER_MAKE_VERSION2(2019,5)
|
||||||
|
#elif (_MSC_VER >= 1924)
|
||||||
|
#define MPT_COMPILER_MSVC_VERSION MPT_COMPILER_MAKE_VERSION2(2019,4)
|
||||||
|
#elif (_MSC_VER >= 1923)
|
||||||
|
#define MPT_COMPILER_MSVC_VERSION MPT_COMPILER_MAKE_VERSION2(2019,3)
|
||||||
|
#elif (_MSC_VER >= 1922)
|
||||||
#define MPT_COMPILER_MSVC_VERSION MPT_COMPILER_MAKE_VERSION2(2019,2)
|
#define MPT_COMPILER_MSVC_VERSION MPT_COMPILER_MAKE_VERSION2(2019,2)
|
||||||
#elif (_MSC_VER >= 1921)
|
#elif (_MSC_VER >= 1921)
|
||||||
#define MPT_COMPILER_MSVC_VERSION MPT_COMPILER_MAKE_VERSION2(2019,1)
|
#define MPT_COMPILER_MSVC_VERSION MPT_COMPILER_MAKE_VERSION2(2019,1)
|
||||||
|
@ -96,8 +104,8 @@
|
||||||
#define MPT_MSVC_AT_LEAST(version,sp) (MPT_COMPILER_MSVC_VERSION >= MPT_COMPILER_MAKE_VERSION2((version),(sp)))
|
#define MPT_MSVC_AT_LEAST(version,sp) (MPT_COMPILER_MSVC_VERSION >= MPT_COMPILER_MAKE_VERSION2((version),(sp)))
|
||||||
#define MPT_MSVC_BEFORE(version,sp) (MPT_COMPILER_MSVC_VERSION < MPT_COMPILER_MAKE_VERSION2((version),(sp)))
|
#define MPT_MSVC_BEFORE(version,sp) (MPT_COMPILER_MSVC_VERSION < MPT_COMPILER_MAKE_VERSION2((version),(sp)))
|
||||||
|
|
||||||
#if MPT_MSVC_BEFORE(2015,0)
|
#if MPT_MSVC_BEFORE(2017,9)
|
||||||
#error "MSVC version 2015 required"
|
#error "MSVC version 2017 15.9 required"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_PREFAST_)
|
#if defined(_PREFAST_)
|
||||||
|
@ -139,29 +147,21 @@
|
||||||
|
|
||||||
#if (__cplusplus >= 201703)
|
#if (__cplusplus >= 201703)
|
||||||
#define MPT_CXX 17
|
#define MPT_CXX 17
|
||||||
#elif (__cplusplus >= 201402)
|
|
||||||
#define MPT_CXX 14
|
|
||||||
#else
|
#else
|
||||||
#define MPT_CXX 11
|
#define MPT_CXX 17
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#elif MPT_COMPILER_MSVC
|
#elif MPT_COMPILER_MSVC
|
||||||
|
|
||||||
#if MPT_MSVC_AT_LEAST(2015,3)
|
|
||||||
#if (_MSVC_LANG >= 201703)
|
#if (_MSVC_LANG >= 201703)
|
||||||
#define MPT_CXX 17
|
#define MPT_CXX 17
|
||||||
#elif (_MSVC_LANG >= 201402)
|
|
||||||
#define MPT_CXX 14
|
|
||||||
#else
|
#else
|
||||||
#define MPT_CXX 11
|
#define MPT_CXX 17
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#define MPT_CXX 11
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define MPT_CXX 11
|
#define MPT_CXX 17
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -205,11 +205,13 @@
|
||||||
#define MPT_OS_EMSCRIPTEN 1
|
#define MPT_OS_EMSCRIPTEN 1
|
||||||
#if defined(__EMSCRIPTEN_major__) && defined(__EMSCRIPTEN_minor__)
|
#if defined(__EMSCRIPTEN_major__) && defined(__EMSCRIPTEN_minor__)
|
||||||
#if (__EMSCRIPTEN_major__ > 1)
|
#if (__EMSCRIPTEN_major__ > 1)
|
||||||
// ok
|
// ok
|
||||||
#elif (__EMSCRIPTEN_major__ == 1) && (__EMSCRIPTEN_minor__ >= 38)
|
#elif (__EMSCRIPTEN_major__ == 1) && (__EMSCRIPTEN_minor__ > 39)
|
||||||
// ok
|
// ok
|
||||||
|
#elif (__EMSCRIPTEN_major__ == 1) && (__EMSCRIPTEN_minor__ == 39) && (__EMSCRIPTEN_tiny__ >= 7)
|
||||||
|
// ok
|
||||||
#else
|
#else
|
||||||
#error "Emscripten >= 1.38 is required."
|
#error "Emscripten >= 1.39.7 is required."
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
|
@ -306,13 +308,59 @@
|
||||||
#define MPT_PLATFORM_MULTITHREADED 0
|
#define MPT_PLATFORM_MULTITHREADED 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if MPT_OS_DJGPP
|
#if MPT_OS_DJGPP
|
||||||
#define MPT_COMPILER_QUIRK_NO_WCHAR
|
#define MPT_COMPILER_QUIRK_NO_WCHAR
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MPT_MSVC_BEFORE(2017,8)
|
|
||||||
// fixed in VS2017 15.8
|
#if defined(__arm__)
|
||||||
// see <https://blogs.msdn.microsoft.com/vcblog/2018/09/18/stl-features-and-fixes-in-vs-2017-15-8/>
|
|
||||||
#define MPT_COMPILER_QUIRK_MSVC_STRINGSTREAM
|
#if defined(__SOFTFP__)
|
||||||
|
#define MPT_COMPILER_QUIRK_FLOAT_EMULATED 1
|
||||||
|
#else
|
||||||
|
#define MPT_COMPILER_QUIRK_FLOAT_EMULATED 0
|
||||||
|
#endif
|
||||||
|
#if defined(__VFP_FP__)
|
||||||
|
// native-endian IEEE754
|
||||||
|
#define MPT_COMPILER_QUIRK_FLOAT_NOTNATIVEENDIAN 0
|
||||||
|
#define MPT_COMPILER_QUIRK_FLOAT_NOTIEEE754 0
|
||||||
|
#elif defined(__MAVERICK__)
|
||||||
|
// little-endian IEEE754, we assume native-endian though
|
||||||
|
#define MPT_COMPILER_QUIRK_FLOAT_NOTNATIVEENDIAN 1
|
||||||
|
#define MPT_COMPILER_QUIRK_FLOAT_NOTIEEE754 0
|
||||||
|
#else
|
||||||
|
// not IEEE754
|
||||||
|
#define MPT_COMPILER_QUIRK_FLOAT_NOTNATIVEENDIAN 1
|
||||||
|
#define MPT_COMPILER_QUIRK_FLOAT_NOTIEEE754 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#elif defined(__mips__)
|
||||||
|
|
||||||
|
#if defined(__mips_soft_float)
|
||||||
|
#define MPT_COMPILER_QUIRK_FLOAT_EMULATED 1
|
||||||
|
#else
|
||||||
|
#define MPT_COMPILER_QUIRK_FLOAT_EMULATED 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MPT_OS_EMSCRIPTEN
|
||||||
|
#define MPT_COMPILER_QUIRK_FLOAT_PREFER64 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MPT_COMPILER_QUIRK_FLOAT_PREFER32
|
||||||
|
#define MPT_COMPILER_QUIRK_FLOAT_PREFER32 0
|
||||||
|
#endif
|
||||||
|
#ifndef MPT_COMPILER_QUIRK_FLOAT_PREFER64
|
||||||
|
#define MPT_COMPILER_QUIRK_FLOAT_PREFER64 0
|
||||||
|
#endif
|
||||||
|
#ifndef MPT_COMPILER_QUIRK_FLOAT_EMULATED
|
||||||
|
#define MPT_COMPILER_QUIRK_FLOAT_EMULATED 0
|
||||||
|
#endif
|
||||||
|
#ifndef MPT_COMPILER_QUIRK_FLOAT_NOTNATIVEENDIAN
|
||||||
|
#define MPT_COMPILER_QUIRK_FLOAT_NOTNATIVEENDIAN 0
|
||||||
|
#endif
|
||||||
|
#ifndef MPT_COMPILER_QUIRK_FLOAT_NOTIEEE754
|
||||||
|
#define MPT_COMPILER_QUIRK_FLOAT_NOTIEEE754 0
|
||||||
|
#endif
|
||||||
|
|
|
@ -191,7 +191,7 @@ void ComponentFactoryBase::PreConstruct() const
|
||||||
{
|
{
|
||||||
MPT_LOG(LogInformation, "Components",
|
MPT_LOG(LogInformation, "Components",
|
||||||
mpt::format(U_("Constructing Component %1"))
|
mpt::format(U_("Constructing Component %1"))
|
||||||
( mpt::ToUnicode(mpt::CharsetASCII, m_ID)
|
( mpt::ToUnicode(mpt::Charset::ASCII, m_ID)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -233,7 +233,7 @@ static ComponentListEntry * & ComponentListHead()
|
||||||
|
|
||||||
bool ComponentListPush(ComponentListEntry *entry)
|
bool ComponentListPush(ComponentListEntry *entry)
|
||||||
{
|
{
|
||||||
MPT_LOCK_GUARD<mpt::mutex> guard(ComponentListMutex());
|
mpt::lock_guard<mpt::mutex> guard(ComponentListMutex());
|
||||||
entry->next = ComponentListHead();
|
entry->next = ComponentListHead();
|
||||||
ComponentListHead() = entry;
|
ComponentListHead() = entry;
|
||||||
return true;
|
return true;
|
||||||
|
@ -267,7 +267,7 @@ std::shared_ptr<ComponentManager> ComponentManager::Instance()
|
||||||
ComponentManager::ComponentManager(const IComponentManagerSettings &settings)
|
ComponentManager::ComponentManager(const IComponentManagerSettings &settings)
|
||||||
: m_Settings(settings)
|
: m_Settings(settings)
|
||||||
{
|
{
|
||||||
MPT_LOCK_GUARD<mpt::mutex> guard(ComponentListMutex());
|
mpt::lock_guard<mpt::mutex> guard(ComponentListMutex());
|
||||||
for(ComponentListEntry *entry = ComponentListHead(); entry; entry = entry->next)
|
for(ComponentListEntry *entry = ComponentListHead(); entry; entry = entry->next)
|
||||||
{
|
{
|
||||||
entry->reg(*this);
|
entry->reg(*this);
|
||||||
|
|
|
@ -318,6 +318,8 @@ public:
|
||||||
virtual bool KeepLoaded() const = 0;
|
virtual bool KeepLoaded() const = 0;
|
||||||
virtual bool IsBlocked(const std::string &key) const = 0;
|
virtual bool IsBlocked(const std::string &key) const = 0;
|
||||||
virtual mpt::PathString Path() const = 0;
|
virtual mpt::PathString Path() const = 0;
|
||||||
|
protected:
|
||||||
|
virtual ~IComponentManagerSettings() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -440,7 +442,7 @@ std::shared_ptr<const type> GetComponent()
|
||||||
{
|
{
|
||||||
static std::weak_ptr<type> cache;
|
static std::weak_ptr<type> cache;
|
||||||
static mpt::mutex m;
|
static mpt::mutex m;
|
||||||
MPT_LOCK_GUARD<mpt::mutex> l(m);
|
mpt::lock_guard<mpt::mutex> l(m);
|
||||||
std::shared_ptr<type> component = cache.lock();
|
std::shared_ptr<type> component = cache.lock();
|
||||||
if(!component)
|
if(!component)
|
||||||
{
|
{
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -16,17 +16,9 @@ OPENMPT_NAMESPACE_BEGIN
|
||||||
|
|
||||||
class FileReaderTraitsMemory;
|
class FileReaderTraitsMemory;
|
||||||
|
|
||||||
#if defined(MPT_FILEREADER_STD_ISTREAM)
|
|
||||||
|
|
||||||
class FileReaderTraitsStdStream;
|
class FileReaderTraitsStdStream;
|
||||||
|
|
||||||
typedef FileReaderTraitsStdStream FileReaderTraitsDefault;
|
using FileReaderTraitsDefault = FileReaderTraitsStdStream;
|
||||||
|
|
||||||
#else // !MPT_FILEREADER_STD_ISTREAM
|
|
||||||
|
|
||||||
typedef FileReaderTraitsMemory FileReaderTraitsDefault;
|
|
||||||
|
|
||||||
#endif // MPT_FILEREADER_STD_ISTREAM
|
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
|
@ -35,9 +27,9 @@ class FileReader;
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
typedef detail::FileReader<FileReaderTraitsDefault> FileReader;
|
using FileReader = detail::FileReader<FileReaderTraitsDefault>;
|
||||||
|
|
||||||
typedef detail::FileReader<FileReaderTraitsMemory> MemoryFileReader;
|
using MemoryFileReader = detail::FileReader<FileReaderTraitsMemory>;
|
||||||
|
|
||||||
OPENMPT_NAMESPACE_END
|
OPENMPT_NAMESPACE_END
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ OPENMPT_NAMESPACE_BEGIN
|
||||||
template <typename Tenum>
|
template <typename Tenum>
|
||||||
struct enum_traits
|
struct enum_traits
|
||||||
{
|
{
|
||||||
typedef typename std::make_unsigned<Tenum>::type store_type;
|
using store_type = typename std::make_unsigned<Tenum>::type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -35,9 +35,9 @@ template <typename enum_t>
|
||||||
class enum_value_type
|
class enum_value_type
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef enum_t enum_type;
|
using enum_type = enum_t;
|
||||||
typedef enum_value_type value_type;
|
using value_type = enum_value_type;
|
||||||
typedef typename enum_traits<enum_t>::store_type store_type;
|
using store_type = typename enum_traits<enum_t>::store_type;
|
||||||
private:
|
private:
|
||||||
store_type bits;
|
store_type bits;
|
||||||
public:
|
public:
|
||||||
|
@ -94,10 +94,10 @@ template <typename enum_t>
|
||||||
class Enum
|
class Enum
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef Enum self_type;
|
using self_type = Enum;
|
||||||
typedef enum_t enum_type;
|
using enum_type = enum_t;
|
||||||
typedef enum_value_type<enum_t> value_type;
|
using value_type = enum_value_type<enum_t>;
|
||||||
typedef typename value_type::store_type store_type;
|
using store_type = typename value_type::store_type;
|
||||||
private:
|
private:
|
||||||
enum_type value;
|
enum_type value;
|
||||||
public:
|
public:
|
||||||
|
@ -150,10 +150,10 @@ template <typename enum_t, typename store_t = typename enum_value_type<enum_t>::
|
||||||
class FlagSet
|
class FlagSet
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef FlagSet self_type;
|
using self_type = FlagSet;
|
||||||
typedef enum_t enum_type;
|
using enum_type = enum_t;
|
||||||
typedef enum_value_type<enum_t> value_type;
|
using value_type = enum_value_type<enum_t>;
|
||||||
typedef store_t store_type;
|
using store_type = store_t;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -195,8 +195,7 @@ public:
|
||||||
{
|
{
|
||||||
return load();
|
return load();
|
||||||
}
|
}
|
||||||
// The macro-based extended instrument fields writer in InstrumentExtensions.cpp currently needs this conversion.
|
MPT_CONSTEXPR11_FUN explicit operator store_type () const noexcept
|
||||||
/*MPT_DEPRECATED*/ MPT_CONSTEXPR11_FUN operator store_type () const noexcept
|
|
||||||
{
|
{
|
||||||
return load().as_bits();
|
return load().as_bits();
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,8 +110,8 @@ void Logger::SendLogMessage(const mpt::source_location &loc, LogLevel level, con
|
||||||
#endif // MODPLUG_TRACKER
|
#endif // MODPLUG_TRACKER
|
||||||
// remove eol if already present and add log level prefix
|
// remove eol if already present and add log level prefix
|
||||||
const mpt::ustring message = LogLevelToString(level) + U_(": ") + mpt::String::RTrim(text, U_("\r\n"));
|
const mpt::ustring message = LogLevelToString(level) + U_(": ") + mpt::String::RTrim(text, U_("\r\n"));
|
||||||
const mpt::ustring file = mpt::ToUnicode(mpt::CharsetASCII, loc.file_name() ? loc.file_name() : "");
|
const mpt::ustring file = mpt::ToUnicode(mpt::CharsetSource, loc.file_name() ? loc.file_name() : "");
|
||||||
const mpt::ustring function = mpt::ToUnicode(mpt::CharsetASCII, loc.function_name() ? loc.function_name() : "");
|
const mpt::ustring function = mpt::ToUnicode(mpt::CharsetSource, loc.function_name() ? loc.function_name() : "");
|
||||||
const mpt::ustring line = mpt::ufmt::dec(loc.line());
|
const mpt::ustring line = mpt::ufmt::dec(loc.line());
|
||||||
#if defined(MODPLUG_TRACKER) && !defined(MPT_BUILD_WINESUPPORT)
|
#if defined(MODPLUG_TRACKER) && !defined(MPT_BUILD_WINESUPPORT)
|
||||||
#if MPT_OS_WINDOWS
|
#if MPT_OS_WINDOWS
|
||||||
|
@ -132,7 +132,7 @@ void Logger::SendLogMessage(const mpt::source_location &loc, LogLevel level, con
|
||||||
}
|
}
|
||||||
if(s_logfile)
|
if(s_logfile)
|
||||||
{
|
{
|
||||||
mpt::IO::WriteText(s_logfile, mpt::ToCharset(mpt::CharsetUTF8, mpt::format(U_("%1+%2 %3(%4): %5 [%6]\n"))
|
mpt::IO::WriteText(s_logfile, mpt::ToCharset(mpt::CharsetLogfile, mpt::format(U_("%1+%2 %3(%4): %5 [%6]\n"))
|
||||||
( mpt::Date::ANSI::ToUString(cur)
|
( mpt::Date::ANSI::ToUString(cur)
|
||||||
, mpt::ufmt::right(6, mpt::ufmt::dec(diff))
|
, mpt::ufmt::right(6, mpt::ufmt::dec(diff))
|
||||||
, file
|
, file
|
||||||
|
@ -168,42 +168,21 @@ void Logger::SendLogMessage(const mpt::source_location &loc, LogLevel level, con
|
||||||
#elif defined(MODPLUG_TRACKER) && defined(MPT_BUILD_WINESUPPORT)
|
#elif defined(MODPLUG_TRACKER) && defined(MPT_BUILD_WINESUPPORT)
|
||||||
std::clog
|
std::clog
|
||||||
<< "NativeSupport: "
|
<< "NativeSupport: "
|
||||||
<< mpt::ToCharset(mpt::CharsetLocaleOrUTF8, file) << "(" << mpt::ToCharset(mpt::CharsetLocaleOrUTF8, line) << ")" << ": "
|
<< mpt::ToCharset(mpt::CharsetStdIO, file) << "(" << mpt::ToCharset(mpt::CharsetStdIO, line) << ")" << ": "
|
||||||
<< mpt::ToCharset(mpt::CharsetLocaleOrUTF8, message)
|
<< mpt::ToCharset(mpt::CharsetStdIO, message)
|
||||||
<< " [" << mpt::ToCharset(mpt::CharsetLocaleOrUTF8, function) << "]"
|
<< " [" << mpt::ToCharset(mpt::CharsetStdIO, function) << "]"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
#else // !MODPLUG_TRACKER
|
#else // !MODPLUG_TRACKER
|
||||||
std::clog
|
std::clog
|
||||||
<< "libopenmpt: "
|
<< "libopenmpt: "
|
||||||
<< mpt::ToCharset(mpt::CharsetLocaleOrUTF8, file) << "(" << mpt::ToCharset(mpt::CharsetLocaleOrUTF8, line) << ")" << ": "
|
<< mpt::ToCharset(mpt::CharsetStdIO, file) << "(" << mpt::ToCharset(mpt::CharsetStdIO, line) << ")" << ": "
|
||||||
<< mpt::ToCharset(mpt::CharsetLocaleOrUTF8, message)
|
<< mpt::ToCharset(mpt::CharsetStdIO, message)
|
||||||
<< " [" << mpt::ToCharset(mpt::CharsetLocaleOrUTF8, function) << "]"
|
<< " [" << mpt::ToCharset(mpt::CharsetStdIO, function) << "]"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
#endif // MODPLUG_TRACKER
|
#endif // MODPLUG_TRACKER
|
||||||
#endif // MPT_LOG_IS_DISABLED
|
#endif // MPT_LOG_IS_DISABLED
|
||||||
}
|
}
|
||||||
|
|
||||||
void LegacyLogger::operator () (const AnyStringLocale &text)
|
|
||||||
{
|
|
||||||
SendLogMessage(loc, MPT_LEGACY_LOGLEVEL, "", text);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LegacyLogger::operator () (const char *format, ...)
|
|
||||||
{
|
|
||||||
static const std::size_t LOGBUF_SIZE = 1024;
|
|
||||||
char message[LOGBUF_SIZE];
|
|
||||||
va_list va;
|
|
||||||
va_start(va, format);
|
|
||||||
vsnprintf(message, LOGBUF_SIZE, format, va);
|
|
||||||
va_end(va);
|
|
||||||
message[LOGBUF_SIZE - 1] = '\0';
|
|
||||||
SendLogMessage(loc, MPT_LEGACY_LOGLEVEL, "", mpt::ToUnicode(mpt::CharsetLocaleOrUTF8, message));
|
|
||||||
}
|
|
||||||
|
|
||||||
void LegacyLogger::operator () (LogLevel level, const mpt::ustring &text)
|
|
||||||
{
|
|
||||||
SendLogMessage(loc, level, "", text);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -219,7 +198,7 @@ namespace Trace {
|
||||||
|
|
||||||
// Debugging functionality will use simple globals.
|
// Debugging functionality will use simple globals.
|
||||||
|
|
||||||
bool volatile g_Enabled = false;
|
std::atomic<bool> g_Enabled = ATOMIC_VAR_INIT(false);
|
||||||
|
|
||||||
static bool g_Sealed = false;
|
static bool g_Sealed = false;
|
||||||
|
|
||||||
|
@ -338,7 +317,7 @@ bool Dump(const mpt::PathString &filename)
|
||||||
|
|
||||||
mpt::ofstream f(filename);
|
mpt::ofstream f(filename);
|
||||||
|
|
||||||
f << "Build: OpenMPT " << mpt::ToCharset(mpt::CharsetUTF8, Build::GetVersionStringExtended()) << std::endl;
|
f << "Build: OpenMPT " << mpt::ToCharset(mpt::CharsetLogfile, Build::GetVersionStringExtended()) << std::endl;
|
||||||
|
|
||||||
bool qpcValid = false;
|
bool qpcValid = false;
|
||||||
|
|
||||||
|
@ -350,7 +329,7 @@ bool Dump(const mpt::PathString &filename)
|
||||||
qpcValid = true;
|
qpcValid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
f << "Dump: " << mpt::ToCharset(mpt::CharsetUTF8, mpt::Date::ANSI::ToUString(ftNow)) << std::endl;
|
f << "Dump: " << mpt::ToCharset(mpt::CharsetLogfile, mpt::Date::ANSI::ToUString(ftNow)) << std::endl;
|
||||||
f << "Captured events: " << Entries.size() << std::endl;
|
f << "Captured events: " << Entries.size() << std::endl;
|
||||||
if(qpcValid && (Entries.size() > 0))
|
if(qpcValid && (Entries.size() > 0))
|
||||||
{
|
{
|
||||||
|
@ -367,7 +346,7 @@ bool Dump(const mpt::PathString &filename)
|
||||||
std::string time;
|
std::string time;
|
||||||
if(qpcValid)
|
if(qpcValid)
|
||||||
{
|
{
|
||||||
time = mpt::ToCharset(mpt::CharsetUTF8, mpt::Date::ANSI::ToUString( ftNow - static_cast<int64>( static_cast<double>(qpcNow.QuadPart - entry.Timestamp) * (10000000.0 / static_cast<double>(qpcFreq.QuadPart) ) ) ) );
|
time = mpt::ToCharset(mpt::CharsetLogfile, mpt::Date::ANSI::ToUString( ftNow - static_cast<int64>( static_cast<double>(qpcNow.QuadPart - entry.Timestamp) * (10000000.0 / static_cast<double>(qpcFreq.QuadPart) ) ) ) );
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
time = mpt::format("0x%1")(mpt::fmt::hex0<16>(entry.Timestamp));
|
time = mpt::format("0x%1")(mpt::fmt::hex0<16>(entry.Timestamp));
|
||||||
|
|
|
@ -11,6 +11,9 @@
|
||||||
|
|
||||||
#include "BuildSettings.h"
|
#include "BuildSettings.h"
|
||||||
|
|
||||||
|
#if defined(MODPLUG_TRACKER) && MPT_OS_WINDOWS
|
||||||
|
#include <atomic>
|
||||||
|
#endif
|
||||||
|
|
||||||
OPENMPT_NAMESPACE_BEGIN
|
OPENMPT_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
@ -110,7 +113,7 @@ namespace log
|
||||||
// All logging code gets compiled and immediately dead-code eliminated.
|
// All logging code gets compiled and immediately dead-code eliminated.
|
||||||
#define MPT_LOG_IS_DISABLED
|
#define MPT_LOG_IS_DISABLED
|
||||||
#endif
|
#endif
|
||||||
static const int GlobalLogLevel = MPT_LOG_GLOBAL_LEVEL ;
|
static constexpr int GlobalLogLevel = MPT_LOG_GLOBAL_LEVEL ;
|
||||||
#else
|
#else
|
||||||
extern int GlobalLogLevel;
|
extern int GlobalLogLevel;
|
||||||
#endif
|
#endif
|
||||||
|
@ -155,35 +158,11 @@ public:
|
||||||
/**/
|
/**/
|
||||||
|
|
||||||
|
|
||||||
#define MPT_LEGACY_LOGLEVEL LogDebug
|
|
||||||
|
|
||||||
class LegacyLogger : public Logger
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
const mpt::source_location loc;
|
|
||||||
public:
|
|
||||||
constexpr LegacyLogger(mpt::source_location loc) noexcept : loc(loc) {}
|
|
||||||
/* MPT_DEPRECATED */ void MPT_PRINTF_FUNC(2,3) operator () (const char *format, ...); // migrate to type-safe MPT_LOG
|
|
||||||
/* MPT_DEPRECATED */ void operator () (const AnyStringLocale &text); // migrate to properly namespaced MPT_LOG
|
|
||||||
/* MPT_DEPRECATED */ void operator () (LogLevel level, const mpt::ustring &text); // migrate to properly namespaced MPT_LOG
|
|
||||||
};
|
|
||||||
|
|
||||||
#define Log MPT_MAYBE_CONSTANT_IF(mpt::log::GlobalLogLevel < MPT_LEGACY_LOGLEVEL) { } else MPT_MAYBE_CONSTANT_IF(!mpt::log::IsFacilityActive("")) { } else mpt::log::LegacyLogger(MPT_SOURCE_LOCATION_CURRENT())
|
|
||||||
|
|
||||||
|
|
||||||
#else // !NO_LOGGING
|
#else // !NO_LOGGING
|
||||||
|
|
||||||
|
|
||||||
#define MPT_LOG(level, facility, text) MPT_DO { } MPT_WHILE_0
|
#define MPT_LOG(level, facility, text) MPT_DO { } MPT_WHILE_0
|
||||||
|
|
||||||
struct LegacyLogger
|
|
||||||
{
|
|
||||||
inline void MPT_PRINTF_FUNC(2,3) operator () (const char * /*format*/ , ...) {}
|
|
||||||
inline void operator () (const AnyStringLocale & /*text*/ ) {}
|
|
||||||
inline void operator () (LogLevel /*level*/ , const mpt::ustring & /*text*/ ) {}
|
|
||||||
};
|
|
||||||
#define Log MPT_CONSTANT_IF(true) {} else mpt::log::LegacyLogger() // completely compile out arguments to Log() so that they do not even get evaluated
|
|
||||||
|
|
||||||
|
|
||||||
#endif // NO_LOGGING
|
#endif // NO_LOGGING
|
||||||
|
|
||||||
|
@ -199,7 +178,7 @@ namespace Trace {
|
||||||
// This cacheline bouncing does not matter at all
|
// This cacheline bouncing does not matter at all
|
||||||
// if there are not multiple thread adding trace points at high frequency (way greater than 1000Hz),
|
// if there are not multiple thread adding trace points at high frequency (way greater than 1000Hz),
|
||||||
// which, in OpenMPT, is only ever the case for just a single thread (the audio thread), if at all.
|
// which, in OpenMPT, is only ever the case for just a single thread (the audio thread), if at all.
|
||||||
extern bool volatile g_Enabled;
|
extern std::atomic<bool> g_Enabled;
|
||||||
static inline bool IsEnabled() { return g_Enabled; }
|
static inline bool IsEnabled() { return g_Enabled; }
|
||||||
|
|
||||||
enum class Direction : int8
|
enum class Direction : int8
|
||||||
|
|
|
@ -52,7 +52,7 @@ struct ProfileBlock
|
||||||
class Statistics * stats;
|
class Statistics * stats;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const std::size_t MAX_PROFILES = 1024;
|
static constexpr std::size_t MAX_PROFILES = 1024;
|
||||||
|
|
||||||
static ProfileBlock Profiles[ MAX_PROFILES ];
|
static ProfileBlock Profiles[ MAX_PROFILES ];
|
||||||
|
|
||||||
|
|
|
@ -98,7 +98,7 @@ public:
|
||||||
/**/
|
/**/
|
||||||
|
|
||||||
|
|
||||||
#define OPENMPT_PROFILE_FUNCTION(cat) OPENMPT_PROFILE_SCOPE(cat, __FUNCTION__)
|
#define OPENMPT_PROFILE_FUNCTION(cat) OPENMPT_PROFILE_SCOPE(cat, __func__)
|
||||||
|
|
||||||
|
|
||||||
#else // !USE_PROFILER
|
#else // !USE_PROFILER
|
||||||
|
|
|
@ -20,13 +20,13 @@ namespace Util
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
static const MPT_UCHAR_TYPE EncodeNibble[16] = {
|
static constexpr mpt::uchar EncodeNibble[16] = {
|
||||||
UC_('0'), UC_('1'), UC_('2'), UC_('3'),
|
UC_('0'), UC_('1'), UC_('2'), UC_('3'),
|
||||||
UC_('4'), UC_('5'), UC_('6'), UC_('7'),
|
UC_('4'), UC_('5'), UC_('6'), UC_('7'),
|
||||||
UC_('8'), UC_('9'), UC_('A'), UC_('B'),
|
UC_('8'), UC_('9'), UC_('A'), UC_('B'),
|
||||||
UC_('C'), UC_('D'), UC_('E'), UC_('F') };
|
UC_('C'), UC_('D'), UC_('E'), UC_('F') };
|
||||||
|
|
||||||
static inline bool DecodeByte(uint8 &byte, MPT_UCHAR_TYPE c1, MPT_UCHAR_TYPE c2)
|
static inline bool DecodeByte(uint8 &byte, mpt::uchar c1, mpt::uchar c2)
|
||||||
{
|
{
|
||||||
byte = 0;
|
byte = 0;
|
||||||
if(UC_('0') <= c1 && c1 <= UC_('9'))
|
if(UC_('0') <= c1 && c1 <= UC_('9'))
|
||||||
|
@ -62,7 +62,7 @@ mpt::ustring BinToHex(mpt::const_byte_span src)
|
||||||
{
|
{
|
||||||
mpt::ustring result;
|
mpt::ustring result;
|
||||||
result.reserve(src.size() * 2);
|
result.reserve(src.size() * 2);
|
||||||
for(mpt::byte byte : src)
|
for(std::byte byte : src)
|
||||||
{
|
{
|
||||||
result.push_back(EncodeNibble[(mpt::byte_cast<uint8>(byte) & 0xf0) >> 4]);
|
result.push_back(EncodeNibble[(mpt::byte_cast<uint8>(byte) & 0xf0) >> 4]);
|
||||||
result.push_back(EncodeNibble[mpt::byte_cast<uint8>(byte) & 0x0f]);
|
result.push_back(EncodeNibble[mpt::byte_cast<uint8>(byte) & 0x0f]);
|
||||||
|
@ -70,9 +70,9 @@ mpt::ustring BinToHex(mpt::const_byte_span src)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<mpt::byte> HexToBin(const mpt::ustring &src)
|
std::vector<std::byte> HexToBin(const mpt::ustring &src)
|
||||||
{
|
{
|
||||||
std::vector<mpt::byte> result;
|
std::vector<std::byte> result;
|
||||||
result.reserve(src.size() / 2);
|
result.reserve(src.size() / 2);
|
||||||
for(std::size_t i = 0; (i + 1) < src.size(); i += 2)
|
for(std::size_t i = 0; (i + 1) < src.size(); i += 2)
|
||||||
{
|
{
|
||||||
|
@ -81,7 +81,7 @@ std::vector<mpt::byte> HexToBin(const mpt::ustring &src)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
result.push_back(mpt::byte_cast<mpt::byte>(byte));
|
result.push_back(mpt::byte_cast<std::byte>(byte));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -207,7 +207,7 @@ namespace Util
|
||||||
namespace Util
|
namespace Util
|
||||||
{
|
{
|
||||||
|
|
||||||
std::vector<mpt::byte> HexToBin(const mpt::ustring &src);
|
std::vector<std::byte> HexToBin(const mpt::ustring &src);
|
||||||
mpt::ustring BinToHex(mpt::const_byte_span src);
|
mpt::ustring BinToHex(mpt::const_byte_span src);
|
||||||
|
|
||||||
template <typename T> inline mpt::ustring BinToHex(mpt::span<T> src) { return Util::BinToHex(mpt::byte_cast<mpt::const_byte_span>(src)); }
|
template <typename T> inline mpt::ustring BinToHex(mpt::span<T> src) { return Util::BinToHex(mpt::byte_cast<mpt::const_byte_span>(src)); }
|
||||||
|
|
|
@ -12,18 +12,6 @@
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "mptAlloc.h"
|
#include "mptAlloc.h"
|
||||||
|
|
||||||
#include "mptBaseTypes.h"
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <new>
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <cstdlib>
|
|
||||||
|
|
||||||
#if MPT_COMPILER_MSVC
|
|
||||||
#include <malloc.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
OPENMPT_NAMESPACE_BEGIN
|
OPENMPT_NAMESPACE_BEGIN
|
||||||
|
@ -37,87 +25,6 @@ OPENMPT_NAMESPACE_BEGIN
|
||||||
namespace mpt
|
namespace mpt
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if MPT_CXX_AT_LEAST(17)
|
|
||||||
#else
|
|
||||||
void* align(std::size_t alignment, std::size_t size, void* &ptr, std::size_t &space) noexcept
|
|
||||||
{
|
|
||||||
std::size_t offset = static_cast<std::size_t>(reinterpret_cast<std::uintptr_t>(ptr) & (alignment - 1));
|
|
||||||
if(offset != 0)
|
|
||||||
{
|
|
||||||
offset = alignment - offset;
|
|
||||||
}
|
|
||||||
if((space < offset) || ((space - offset) < size))
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
ptr = static_cast<mpt::byte*>(ptr) + offset;
|
|
||||||
space -= offset;
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
aligned_raw_memory aligned_alloc_impl(std::size_t size, std::size_t count, std::size_t alignment)
|
|
||||||
{
|
|
||||||
#if MPT_CXX_AT_LEAST(17) && !defined(MPT_COMPILER_QUIRK_NO_ALIGNEDALLOC)
|
|
||||||
std::size_t space = count * size;
|
|
||||||
void* mem = std::aligned_alloc(alignment, space);
|
|
||||||
if(!mem)
|
|
||||||
{
|
|
||||||
MPT_EXCEPTION_THROW_OUT_OF_MEMORY();
|
|
||||||
}
|
|
||||||
return aligned_raw_memory{mem, mem};
|
|
||||||
#elif MPT_COMPILER_MSVC || (defined(__clang__) && defined(_MSC_VER))
|
|
||||||
std::size_t space = count * size;
|
|
||||||
void* mem = _aligned_malloc(space, alignment);
|
|
||||||
if(!mem)
|
|
||||||
{
|
|
||||||
MPT_EXCEPTION_THROW_OUT_OF_MEMORY();
|
|
||||||
}
|
|
||||||
return aligned_raw_memory{mem, mem};
|
|
||||||
#else
|
|
||||||
if(alignment > alignof(mpt::max_align_t))
|
|
||||||
{
|
|
||||||
std::size_t space = count * size + (alignment - 1);
|
|
||||||
void* mem = std::malloc(space);
|
|
||||||
if(!mem)
|
|
||||||
{
|
|
||||||
MPT_EXCEPTION_THROW_OUT_OF_MEMORY();
|
|
||||||
}
|
|
||||||
void* aligned_mem = mem;
|
|
||||||
void* aligned = mpt::align(alignment, size * count, aligned_mem, space);
|
|
||||||
if(!aligned)
|
|
||||||
{
|
|
||||||
MPT_EXCEPTION_THROW_OUT_OF_MEMORY();
|
|
||||||
}
|
|
||||||
return aligned_raw_memory{aligned, mem};
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
std::size_t space = count * size;
|
|
||||||
void* mem = std::malloc(space);
|
|
||||||
if(!mem)
|
|
||||||
{
|
|
||||||
MPT_EXCEPTION_THROW_OUT_OF_MEMORY();
|
|
||||||
}
|
|
||||||
return aligned_raw_memory{mem, mem};
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void aligned_free(aligned_raw_memory raw)
|
|
||||||
{
|
|
||||||
#if MPT_CXX_AT_LEAST(17) && !defined(MPT_COMPILER_QUIRK_NO_ALIGNEDALLOC)
|
|
||||||
std::free(raw.mem);
|
|
||||||
#elif MPT_COMPILER_MSVC || (defined(__clang__) && defined(_MSC_VER))
|
|
||||||
_aligned_free(raw.mem);
|
|
||||||
#else
|
|
||||||
std::free(raw.mem);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace mpt
|
} // namespace mpt
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,9 @@
|
||||||
#include "mptMemory.h"
|
#include "mptMemory.h"
|
||||||
#include "mptSpan.h"
|
#include "mptSpan.h"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <utility>
|
#include <new>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,9 +33,9 @@ namespace mpt {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <typename T> inline span<T> as_span(std::vector<T> & cont) { return span<T>(cont); }
|
template <typename T> inline mpt::span<T> as_span(std::vector<T> & cont) { return mpt::span<T>(cont); }
|
||||||
|
|
||||||
template <typename T> inline span<const T> as_span(const std::vector<T> & cont) { return span<const T>(cont); }
|
template <typename T> inline mpt::span<const T> as_span(const std::vector<T> & cont) { return mpt::span<const T>(cont); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -53,13 +54,13 @@ struct GetRawBytesFunctor<std::vector<T>>
|
||||||
{
|
{
|
||||||
inline mpt::const_byte_span operator () (const std::vector<T> & v) const
|
inline mpt::const_byte_span operator () (const std::vector<T> & v) const
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(mpt::is_binary_safe<typename std::remove_const<T>::type>::value);
|
static_assert(mpt::is_binary_safe<typename std::remove_const<T>::type>::value);
|
||||||
return mpt::as_span(reinterpret_cast<const mpt::byte *>(v.data()), v.size() * sizeof(T));
|
return mpt::as_span(reinterpret_cast<const std::byte *>(v.data()), v.size() * sizeof(T));
|
||||||
}
|
}
|
||||||
inline mpt::byte_span operator () (std::vector<T> & v) const
|
inline mpt::byte_span operator () (std::vector<T> & v) const
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(mpt::is_binary_safe<typename std::remove_const<T>::type>::value);
|
static_assert(mpt::is_binary_safe<typename std::remove_const<T>::type>::value);
|
||||||
return mpt::as_span(reinterpret_cast<mpt::byte *>(v.data()), v.size() * sizeof(T));
|
return mpt::as_span(reinterpret_cast<std::byte *>(v.data()), v.size() * sizeof(T));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -68,8 +69,8 @@ struct GetRawBytesFunctor<const std::vector<T>>
|
||||||
{
|
{
|
||||||
inline mpt::const_byte_span operator () (const std::vector<T> & v) const
|
inline mpt::const_byte_span operator () (const std::vector<T> & v) const
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(mpt::is_binary_safe<typename std::remove_const<T>::type>::value);
|
static_assert(mpt::is_binary_safe<typename std::remove_const<T>::type>::value);
|
||||||
return mpt::as_span(reinterpret_cast<const mpt::byte *>(v.data()), v.size() * sizeof(T));
|
return mpt::as_span(reinterpret_cast<const std::byte *>(v.data()), v.size() * sizeof(T));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -79,22 +80,6 @@ struct GetRawBytesFunctor<const std::vector<T>>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if MPT_CXX_AT_LEAST(14)
|
|
||||||
namespace mpt {
|
|
||||||
using std::make_unique;
|
|
||||||
} // namespace mpt
|
|
||||||
#else
|
|
||||||
namespace mpt {
|
|
||||||
template<typename T, typename... Args>
|
|
||||||
std::unique_ptr<T> make_unique(Args&&... args)
|
|
||||||
{
|
|
||||||
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
|
|
||||||
}
|
|
||||||
} // namespace mpt
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(MPT_ENABLE_ALIGNED_ALLOC)
|
#if defined(MPT_ENABLE_ALIGNED_ALLOC)
|
||||||
|
|
||||||
|
|
||||||
|
@ -104,7 +89,7 @@ namespace mpt
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if MPT_CXX_AT_LEAST(17) && !(MPT_COMPILER_CLANG && defined(__GLIBCXX__)) && !(MPT_COMPILER_CLANG && MPT_OS_MACOSX_OR_IOS)
|
#if !(MPT_COMPILER_CLANG && defined(__GLIBCXX__)) && !(MPT_COMPILER_CLANG && MPT_OS_MACOSX_OR_IOS)
|
||||||
using std::launder;
|
using std::launder;
|
||||||
#else
|
#else
|
||||||
template <class T>
|
template <class T>
|
||||||
|
@ -115,147 +100,17 @@ MPT_NOINLINE T* launder(T* p) noexcept
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if MPT_CXX_AT_LEAST(17)
|
|
||||||
using std::align;
|
|
||||||
#else
|
|
||||||
// pre-C++17, std::align does not support over-alignement
|
|
||||||
void* align(std::size_t alignment, std::size_t size, void* &ptr, std::size_t &space) noexcept;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
template <typename T, std::size_t count, std::align_val_t alignment>
|
||||||
|
struct alignas(static_cast<std::size_t>(alignment)) aligned_array
|
||||||
struct aligned_raw_memory
|
: std::array<T, count>
|
||||||
{
|
{
|
||||||
void* aligned;
|
static_assert(static_cast<std::size_t>(alignment) >= alignof(T));
|
||||||
void* mem;
|
static_assert(((count * sizeof(T)) % static_cast<std::size_t>(alignment)) == 0);
|
||||||
|
static_assert(sizeof(std::array<T, count>) == (sizeof(T) * count));
|
||||||
};
|
};
|
||||||
|
|
||||||
aligned_raw_memory aligned_alloc_impl(std::size_t size, std::size_t count, std::size_t alignment);
|
static_assert(sizeof(mpt::aligned_array<float, 4, std::align_val_t{sizeof(float) * 4}>) == sizeof(std::array<float, 4>));
|
||||||
|
|
||||||
template <std::size_t alignment>
|
|
||||||
inline aligned_raw_memory aligned_alloc(std::size_t size, std::size_t count)
|
|
||||||
{
|
|
||||||
MPT_STATIC_ASSERT(alignment > 0);
|
|
||||||
MPT_CONSTEXPR14_ASSERT(mpt::weight(alignment) == 1);
|
|
||||||
return aligned_alloc_impl(size, count, alignment);
|
|
||||||
}
|
|
||||||
|
|
||||||
void aligned_free(aligned_raw_memory raw);
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct aligned_raw_buffer
|
|
||||||
{
|
|
||||||
T* elements;
|
|
||||||
void* mem;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, std::size_t alignment>
|
|
||||||
inline aligned_raw_buffer<T> aligned_alloc(std::size_t count)
|
|
||||||
{
|
|
||||||
MPT_STATIC_ASSERT(alignment >= alignof(T));
|
|
||||||
aligned_raw_memory raw = aligned_alloc<alignment>(sizeof(T), count);
|
|
||||||
return aligned_raw_buffer<T>{mpt::launder(reinterpret_cast<T*>(raw.aligned)), raw.mem};
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline void aligned_free(aligned_raw_buffer<T> buf)
|
|
||||||
{
|
|
||||||
aligned_free(aligned_raw_memory{buf.elements, buf.mem});
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct aligned_raw_objects
|
|
||||||
{
|
|
||||||
T* elements;
|
|
||||||
std::size_t count;
|
|
||||||
void* mem;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, std::size_t alignment>
|
|
||||||
inline aligned_raw_objects<T> aligned_new(std::size_t count, T init = T())
|
|
||||||
{
|
|
||||||
aligned_raw_buffer<T> buf = aligned_alloc<T, alignment>(count);
|
|
||||||
std::size_t constructed = 0;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
for(std::size_t i = 0; i < count; ++i)
|
|
||||||
{
|
|
||||||
new(&(buf.elements[i])) T(init);
|
|
||||||
constructed++;
|
|
||||||
}
|
|
||||||
} MPT_EXCEPTION_CATCH_OUT_OF_MEMORY(e)
|
|
||||||
{
|
|
||||||
while(constructed--)
|
|
||||||
{
|
|
||||||
mpt::launder(&(buf.elements[constructed - 1]))->~T();
|
|
||||||
}
|
|
||||||
aligned_free(buf);
|
|
||||||
MPT_EXCEPTION_RETHROW_OUT_OF_MEMORY(e);
|
|
||||||
} catch(...)
|
|
||||||
{
|
|
||||||
while(constructed--)
|
|
||||||
{
|
|
||||||
mpt::launder(&(buf.elements[constructed - 1]))->~T();
|
|
||||||
}
|
|
||||||
aligned_free(buf);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
return aligned_raw_objects<T>{mpt::launder(buf.elements), count, buf.mem};
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline void aligned_delete(aligned_raw_objects<T> objs)
|
|
||||||
{
|
|
||||||
if(objs.elements)
|
|
||||||
{
|
|
||||||
std::size_t constructed = objs.count;
|
|
||||||
while(constructed--)
|
|
||||||
{
|
|
||||||
objs.elements[constructed - 1].~T();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
aligned_free(aligned_raw_buffer<T>{objs.elements, objs.mem});
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, std::size_t alignment>
|
|
||||||
class aligned_buffer
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
aligned_raw_objects<T> objs;
|
|
||||||
public:
|
|
||||||
explicit aligned_buffer(std::size_t count = 0)
|
|
||||||
: objs(aligned_new<T, alignment>(count))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
aligned_buffer(const aligned_buffer&) = delete;
|
|
||||||
aligned_buffer& operator=(const aligned_buffer&) = delete;
|
|
||||||
~aligned_buffer()
|
|
||||||
{
|
|
||||||
aligned_delete(objs);
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
void destructive_resize(std::size_t count)
|
|
||||||
{
|
|
||||||
aligned_raw_objects<T> tmpobjs = aligned_new<T, alignment>(count);
|
|
||||||
{
|
|
||||||
using namespace std;
|
|
||||||
swap(objs, tmpobjs);
|
|
||||||
}
|
|
||||||
aligned_delete(tmpobjs);
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
T* begin() noexcept { return objs.elements; }
|
|
||||||
const T* begin() const noexcept { return objs.elements; }
|
|
||||||
T* end() noexcept { return objs.elements + objs.count; }
|
|
||||||
const T* end() const noexcept { return objs.elements + objs.count; }
|
|
||||||
const T* cbegin() const noexcept { return objs.elements; }
|
|
||||||
const T* cend() const noexcept { return objs.elements + objs.count; }
|
|
||||||
T& operator[](std::size_t i) noexcept { return objs.elements[i]; }
|
|
||||||
const T& operator[](std::size_t i) const noexcept { return objs.elements[i]; }
|
|
||||||
T* data() noexcept { return objs.elements; }
|
|
||||||
const T* data() const noexcept { return objs.elements; }
|
|
||||||
std::size_t size() const noexcept { return objs.count; }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ OPENMPT_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(_MFC_VER) && !defined(MPT_CPPCHECK_CUSTOM)
|
#if defined(MPT_WITH_MFC) && !defined(MPT_CPPCHECK_CUSTOM)
|
||||||
|
|
||||||
#if !defined(ASSERT)
|
#if !defined(ASSERT)
|
||||||
#error "MFC is expected to #define ASSERT"
|
#error "MFC is expected to #define ASSERT"
|
||||||
|
@ -72,7 +72,7 @@ OPENMPT_NAMESPACE_BEGIN
|
||||||
// let MFC handle our asserts
|
// let MFC handle our asserts
|
||||||
#define MPT_ASSERT_USE_FRAMEWORK 1
|
#define MPT_ASSERT_USE_FRAMEWORK 1
|
||||||
|
|
||||||
#else // !_MFC_VER
|
#else // !MPT_WITH_MFC
|
||||||
|
|
||||||
#if defined(ASSERT)
|
#if defined(ASSERT)
|
||||||
#define MPT_FRAMEWORK_ASSERT_IS_DEFINED
|
#define MPT_FRAMEWORK_ASSERT_IS_DEFINED
|
||||||
|
@ -86,7 +86,7 @@ OPENMPT_NAMESPACE_BEGIN
|
||||||
// handle assert in our own way without relying on some platform-/framework-specific assert implementation
|
// handle assert in our own way without relying on some platform-/framework-specific assert implementation
|
||||||
#define MPT_ASSERT_USE_FRAMEWORK 0
|
#define MPT_ASSERT_USE_FRAMEWORK 0
|
||||||
|
|
||||||
#endif // _MFC_VER
|
#endif // MPT_WITH_MFC
|
||||||
|
|
||||||
#if defined(MPT_FRAMEWORK_ASSERT_IS_DEFINED) && (MPT_ASSERT_USE_FRAMEWORK == 1)
|
#if defined(MPT_FRAMEWORK_ASSERT_IS_DEFINED) && (MPT_ASSERT_USE_FRAMEWORK == 1)
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ OPENMPT_NAMESPACE_BEGIN
|
||||||
|
|
||||||
#else // !NO_ASSERTS
|
#else // !NO_ASSERTS
|
||||||
|
|
||||||
#define MPT_ASSERT_NOTREACHED() MPT_DO { MPT_CONSTANT_IF(!(0)) { AssertHandler(MPT_SOURCE_LOCATION_CURRENT(), "0"); } MPT_CHECKER_ASSUME(0); } MPT_WHILE_0
|
#define MPT_ASSERT_NOTREACHED() MPT_DO { if constexpr(!(0)) { AssertHandler(MPT_SOURCE_LOCATION_CURRENT(), "0"); } MPT_CHECKER_ASSUME(0); } MPT_WHILE_0
|
||||||
#define MPT_ASSERT(expr) MPT_DO { if(!(expr)) { AssertHandler(MPT_SOURCE_LOCATION_CURRENT(), #expr); } MPT_CHECKER_ASSUME(expr); } MPT_WHILE_0
|
#define MPT_ASSERT(expr) MPT_DO { if(!(expr)) { AssertHandler(MPT_SOURCE_LOCATION_CURRENT(), #expr); } MPT_CHECKER_ASSUME(expr); } MPT_WHILE_0
|
||||||
#define MPT_ASSERT_MSG(expr, msg) MPT_DO { if(!(expr)) { AssertHandler(MPT_SOURCE_LOCATION_CURRENT(), #expr, msg); } MPT_CHECKER_ASSUME(expr); } MPT_WHILE_0
|
#define MPT_ASSERT_MSG(expr, msg) MPT_DO { if(!(expr)) { AssertHandler(MPT_SOURCE_LOCATION_CURRENT(), #expr, msg); } MPT_CHECKER_ASSUME(expr); } MPT_WHILE_0
|
||||||
#define MPT_ASSERT_ALWAYS(expr) MPT_DO { if(!(expr)) { AssertHandler(MPT_SOURCE_LOCATION_CURRENT(), #expr); } MPT_CHECKER_ASSUME(expr); } MPT_WHILE_0
|
#define MPT_ASSERT_ALWAYS(expr) MPT_DO { if(!(expr)) { AssertHandler(MPT_SOURCE_LOCATION_CURRENT(), #expr); } MPT_CHECKER_ASSUME(expr); } MPT_WHILE_0
|
||||||
|
@ -136,17 +136,9 @@ MPT_NOINLINE void AssertHandler(const mpt::source_location &loc, const char *exp
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define MPT_CONSTEXPR11_ASSERT MPT_STATIC_ASSERT
|
#define MPT_CONSTEXPR11_ASSERT static_assert
|
||||||
#if MPT_CXX_AT_LEAST(14) && !MPT_MSVC_BEFORE(2017,5)
|
#define MPT_CONSTEXPR14_ASSERT static_assert
|
||||||
#define MPT_CONSTEXPR14_ASSERT MPT_STATIC_ASSERT
|
#define MPT_CONSTEXPR17_ASSERT static_assert
|
||||||
#else
|
|
||||||
#define MPT_CONSTEXPR14_ASSERT MPT_ASSERT
|
|
||||||
#endif
|
|
||||||
#if MPT_CXX_AT_LEAST(17) && !MPT_MSVC_BEFORE(2017,5)
|
|
||||||
#define MPT_CONSTEXPR17_ASSERT MPT_STATIC_ASSERT
|
|
||||||
#else
|
|
||||||
#define MPT_CONSTEXPR17_ASSERT MPT_ASSERT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,9 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
@ -28,14 +30,44 @@ OPENMPT_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Compile time assert.
|
#define MPT_PP_DEFER(m, ...) m(__VA_ARGS__)
|
||||||
#if (MPT_CXX >= 17)
|
|
||||||
#define MPT_STATIC_ASSERT static_assert
|
#define MPT_PP_STRINGIFY(x) #x
|
||||||
|
|
||||||
|
#define MPT_PP_JOIN_HELPER(a, b) a ## b
|
||||||
|
#define MPT_PP_JOIN(a, b) MPT_PP_JOIN_HELPER(a, b)
|
||||||
|
|
||||||
|
#define MPT_PP_UNIQUE_IDENTIFIER(prefix) MPT_PP_JOIN(prefix , __LINE__)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if MPT_COMPILER_MSVC
|
||||||
|
|
||||||
|
#define MPT_WARNING(text) __pragma(message(__FILE__ "(" MPT_PP_DEFER(MPT_PP_STRINGIFY, __LINE__) "): Warning: " text))
|
||||||
|
#define MPT_WARNING_STATEMENT(text) __pragma(message(__FILE__ "(" MPT_PP_DEFER(MPT_PP_STRINGIFY, __LINE__) "): Warning: " text))
|
||||||
|
|
||||||
|
#elif MPT_COMPILER_GCC || MPT_COMPILER_CLANG
|
||||||
|
|
||||||
|
#define MPT_WARNING(text) _Pragma(MPT_PP_STRINGIFY(GCC warning text))
|
||||||
|
#define MPT_WARNING_STATEMENT(text) _Pragma(MPT_PP_STRINGIFY(GCC warning text))
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#define MPT_STATIC_ASSERT(expr) static_assert((expr), "compile time assertion failed: " #expr)
|
|
||||||
|
// portable #pragma message or #warning replacement
|
||||||
|
#define MPT_WARNING(text) \
|
||||||
|
static inline int MPT_PP_UNIQUE_IDENTIFIER(MPT_WARNING_NAME) () noexcept { \
|
||||||
|
int warning [[deprecated("Warning: " text)]] = 0; \
|
||||||
|
return warning; \
|
||||||
|
} \
|
||||||
|
/**/
|
||||||
|
#define MPT_WARNING_STATEMENT(text) \
|
||||||
|
int MPT_PP_UNIQUE_IDENTIFIER(MPT_WARNING_NAME) = [](){ \
|
||||||
|
int warning [[deprecated("Warning: " text)]] = 0; \
|
||||||
|
return warning; \
|
||||||
|
}() \
|
||||||
|
/**/
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
// legacy
|
|
||||||
#define STATIC_ASSERT(x) MPT_STATIC_ASSERT(x)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -55,43 +87,76 @@ OPENMPT_NAMESPACE_BEGIN
|
||||||
|
|
||||||
// constexpr
|
// constexpr
|
||||||
#define MPT_CONSTEXPR11_FUN constexpr MPT_FORCEINLINE
|
#define MPT_CONSTEXPR11_FUN constexpr MPT_FORCEINLINE
|
||||||
#define MPT_CONSTEXPR11_VAR constexpr
|
|
||||||
#if MPT_CXX_AT_LEAST(14) && !MPT_MSVC_BEFORE(2017,5)
|
|
||||||
#define MPT_CONSTEXPR14_FUN constexpr MPT_FORCEINLINE
|
#define MPT_CONSTEXPR14_FUN constexpr MPT_FORCEINLINE
|
||||||
#define MPT_CONSTEXPR14_VAR constexpr
|
|
||||||
#else
|
|
||||||
#define MPT_CONSTEXPR14_FUN MPT_FORCEINLINE
|
|
||||||
#define MPT_CONSTEXPR14_VAR const
|
|
||||||
#endif
|
|
||||||
#if MPT_CXX_AT_LEAST(17) && !MPT_MSVC_BEFORE(2017,5)
|
|
||||||
#define MPT_CONSTEXPR17_FUN constexpr MPT_FORCEINLINE
|
#define MPT_CONSTEXPR17_FUN constexpr MPT_FORCEINLINE
|
||||||
#define MPT_CONSTEXPR17_VAR constexpr
|
#if MPT_CXX_AT_LEAST(20)
|
||||||
#else
|
#define MPT_CONSTEXPR20_FUN constexpr MPT_FORCEINLINE
|
||||||
#define MPT_CONSTEXPR17_FUN MPT_FORCEINLINE
|
#define MPT_CONSTEXPR20_VAR constexpr
|
||||||
#define MPT_CONSTEXPR17_VAR const
|
#else // !C++20
|
||||||
#endif
|
#define MPT_CONSTEXPR20_FUN MPT_FORCEINLINE
|
||||||
|
#define MPT_CONSTEXPR20_VAR const
|
||||||
|
#endif // C++20
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// C++17 std::size
|
namespace mpt
|
||||||
#if MPT_CXX_AT_LEAST(17)
|
{
|
||||||
namespace mpt {
|
template <auto V> struct constant_value { static constexpr decltype(V) value() { return V; } };
|
||||||
using std::size;
|
#define MPT_FORCE_CONSTEXPR(expr) (mpt::constant_value<( expr )>::value())
|
||||||
} // namespace mpt
|
} // namespace mpt
|
||||||
#else
|
|
||||||
namespace mpt {
|
|
||||||
|
|
||||||
|
#if MPT_CXX_AT_LEAST(20)
|
||||||
|
#define MPT_IS_CONSTANT_EVALUATED20() std::is_constant_evaluated()
|
||||||
|
#define MPT_IS_CONSTANT_EVALUATED() std::is_constant_evaluated()
|
||||||
|
#else // !C++20
|
||||||
|
#define MPT_IS_CONSTANT_EVALUATED20() false
|
||||||
|
// this pessimizes the case for C++17 by always assuming constexpr context, which implies always running constexpr-friendly code
|
||||||
|
#define MPT_IS_CONSTANT_EVALUATED() true
|
||||||
|
#endif // C++20
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace mpt
|
||||||
|
{
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
MPT_CONSTEXPR11_FUN auto size(const T & v) -> decltype(v.size())
|
struct stdarray_extent : std::integral_constant<std::size_t, 0> {};
|
||||||
{
|
|
||||||
return v.size();
|
|
||||||
}
|
|
||||||
template <typename T, std::size_t N>
|
template <typename T, std::size_t N>
|
||||||
MPT_CONSTEXPR11_FUN std::size_t size(const T(&)[N]) noexcept
|
struct stdarray_extent<std::array<T, N>> : std::integral_constant<std::size_t, N> {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_stdarray : std::false_type {};
|
||||||
|
|
||||||
|
template <typename T, std::size_t N>
|
||||||
|
struct is_stdarray<std::array<T, N>> : std::true_type {};
|
||||||
|
|
||||||
|
// mpt::extent is the same as std::extent,
|
||||||
|
// but also works for std::array,
|
||||||
|
// and asserts that the given type is actually an array type instead of returning 0.
|
||||||
|
// use as:
|
||||||
|
// mpt::extent<decltype(expr)>()
|
||||||
|
// mpt::extent<decltype(variable)>()
|
||||||
|
// mpt::extent<decltype(type)>()
|
||||||
|
// mpt::extent<type>()
|
||||||
|
template <typename T>
|
||||||
|
constexpr std::size_t extent() noexcept
|
||||||
{
|
{
|
||||||
return N;
|
using Tarray = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
|
||||||
|
static_assert(std::is_array<Tarray>::value || mpt::is_stdarray<Tarray>::value);
|
||||||
|
if constexpr(mpt::is_stdarray<Tarray>::value)
|
||||||
|
{
|
||||||
|
return mpt::stdarray_extent<Tarray>();
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
return std::extent<Tarray>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mpt
|
} // namespace mpt
|
||||||
#endif
|
|
||||||
// legacy
|
// legacy
|
||||||
#if MPT_COMPILER_MSVC
|
#if MPT_COMPILER_MSVC
|
||||||
OPENMPT_NAMESPACE_END
|
OPENMPT_NAMESPACE_END
|
||||||
|
@ -115,41 +180,12 @@ OPENMPT_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Some functions might be deprecated although they are still in use.
|
#define MPT_ATTR_NODISCARD [[nodiscard]]
|
||||||
// Tag them with "MPT_DEPRECATED".
|
#define MPT_DISCARD(expr) static_cast<void>(expr)
|
||||||
#if MPT_COMPILER_MSVC
|
|
||||||
#define MPT_DEPRECATED __declspec(deprecated)
|
|
||||||
#elif MPT_COMPILER_GCC || MPT_COMPILER_CLANG
|
|
||||||
#define MPT_DEPRECATED __attribute__((deprecated))
|
|
||||||
#else
|
|
||||||
#define MPT_DEPRECATED
|
|
||||||
#endif
|
|
||||||
#if defined(MODPLUG_TRACKER)
|
|
||||||
#define MPT_DEPRECATED_TRACKER MPT_DEPRECATED
|
|
||||||
#define MPT_DEPRECATED_LIBOPENMPT
|
|
||||||
#elif defined(LIBOPENMPT_BUILD)
|
|
||||||
#define MPT_DEPRECATED_TRACKER
|
|
||||||
#define MPT_DEPRECATED_LIBOPENMPT MPT_DEPRECATED
|
|
||||||
#else
|
|
||||||
#define MPT_DEPRECATED_TRACKER MPT_DEPRECATED
|
|
||||||
#define MPT_DEPRECATED_LIBOPENMPT MPT_DEPRECATED
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if MPT_CXX_AT_LEAST(17)
|
|
||||||
#define MPT_CONSTANT_IF if constexpr
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if MPT_COMPILER_MSVC
|
#if MPT_COMPILER_MSVC
|
||||||
#if !defined(MPT_CONSTANT_IF)
|
|
||||||
#define MPT_CONSTANT_IF(x) \
|
|
||||||
__pragma(warning(push)) \
|
|
||||||
__pragma(warning(disable:4127)) \
|
|
||||||
if(x) \
|
|
||||||
__pragma(warning(pop)) \
|
|
||||||
/**/
|
|
||||||
#endif
|
|
||||||
#define MPT_MAYBE_CONSTANT_IF(x) \
|
#define MPT_MAYBE_CONSTANT_IF(x) \
|
||||||
__pragma(warning(push)) \
|
__pragma(warning(push)) \
|
||||||
__pragma(warning(disable:4127)) \
|
__pragma(warning(disable:4127)) \
|
||||||
|
@ -178,11 +214,6 @@ OPENMPT_NAMESPACE_BEGIN
|
||||||
/**/
|
/**/
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(MPT_CONSTANT_IF)
|
|
||||||
// MPT_CONSTANT_IF disables compiler warnings for conditions that are either always true or always false for some reason (dependent on template arguments for example)
|
|
||||||
#define MPT_CONSTANT_IF(x) if(x)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(MPT_MAYBE_CONSTANT_IF)
|
#if !defined(MPT_MAYBE_CONSTANT_IF)
|
||||||
// MPT_MAYBE_CONSTANT_IF disables compiler warnings for conditions that may in some case be either always false or always true (this may turn out to be useful in ASSERTions in some cases).
|
// MPT_MAYBE_CONSTANT_IF disables compiler warnings for conditions that may in some case be either always false or always true (this may turn out to be useful in ASSERTions in some cases).
|
||||||
#define MPT_MAYBE_CONSTANT_IF(x) if(x)
|
#define MPT_MAYBE_CONSTANT_IF(x) if(x)
|
||||||
|
@ -217,35 +248,6 @@ OPENMPT_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Macro for marking intentional fall-throughs in switch statements - can be used for static analysis if supported.
|
|
||||||
#if (MPT_CXX >= 17)
|
|
||||||
#define MPT_FALLTHROUGH [[fallthrough]]
|
|
||||||
#elif MPT_COMPILER_MSVC
|
|
||||||
#define MPT_FALLTHROUGH __fallthrough
|
|
||||||
#elif MPT_COMPILER_CLANG
|
|
||||||
#define MPT_FALLTHROUGH [[clang::fallthrough]]
|
|
||||||
#elif MPT_COMPILER_GCC && MPT_GCC_AT_LEAST(7,1,0)
|
|
||||||
#define MPT_FALLTHROUGH __attribute__((fallthrough))
|
|
||||||
#elif defined(__has_cpp_attribute)
|
|
||||||
#if __has_cpp_attribute(fallthrough)
|
|
||||||
#define MPT_FALLTHROUGH [[fallthrough]]
|
|
||||||
#else
|
|
||||||
#define MPT_FALLTHROUGH MPT_DO { } MPT_WHILE_0
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#define MPT_FALLTHROUGH MPT_DO { } MPT_WHILE_0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if MPT_COMPILER_GCC || MPT_COMPILER_CLANG
|
|
||||||
#define MPT_PRINTF_FUNC(formatstringindex,varargsindex) __attribute__((format(printf, formatstringindex, varargsindex)))
|
|
||||||
#else
|
|
||||||
#define MPT_PRINTF_FUNC(formatstringindex,varargsindex)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if MPT_COMPILER_MSVC
|
#if MPT_COMPILER_MSVC
|
||||||
// warning LNK4221: no public symbols found; archive member will be inaccessible
|
// warning LNK4221: no public symbols found; archive member will be inaccessible
|
||||||
// There is no way to selectively disable linker warnings.
|
// There is no way to selectively disable linker warnings.
|
||||||
|
|
|
@ -18,13 +18,13 @@
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#if MPT_CXX_AT_LEAST(20)
|
||||||
|
#include <source_location>
|
||||||
|
#endif // C++20
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#if MPT_GCC_BEFORE(4,9,0)
|
|
||||||
#include <stddef.h>
|
|
||||||
#endif
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,14 +33,34 @@ OPENMPT_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef std::int8_t int8;
|
namespace mpt
|
||||||
typedef std::int16_t int16;
|
{
|
||||||
typedef std::int32_t int32;
|
template <bool cond, typename Ta, typename Tb>
|
||||||
typedef std::int64_t int64;
|
struct select_type
|
||||||
typedef std::uint8_t uint8;
|
{
|
||||||
typedef std::uint16_t uint16;
|
};
|
||||||
typedef std::uint32_t uint32;
|
template <typename Ta, typename Tb>
|
||||||
typedef std::uint64_t uint64;
|
struct select_type<true, Ta, Tb>
|
||||||
|
{
|
||||||
|
using type = Ta;
|
||||||
|
};
|
||||||
|
template <typename Ta, typename Tb>
|
||||||
|
struct select_type<false, Ta, Tb>
|
||||||
|
{
|
||||||
|
using type = Tb;
|
||||||
|
};
|
||||||
|
} // namespace mpt
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
using int8 = std::int8_t;
|
||||||
|
using int16 = std::int16_t;
|
||||||
|
using int32 = std::int32_t;
|
||||||
|
using int64 = std::int64_t;
|
||||||
|
using uint8 = std::uint8_t;
|
||||||
|
using uint16 = std::uint16_t;
|
||||||
|
using uint32 = std::uint32_t;
|
||||||
|
using uint64 = std::uint64_t;
|
||||||
|
|
||||||
constexpr int8 int8_min = std::numeric_limits<int8>::min();
|
constexpr int8 int8_min = std::numeric_limits<int8>::min();
|
||||||
constexpr int16 int16_min = std::numeric_limits<int16>::min();
|
constexpr int16 int16_min = std::numeric_limits<int16>::min();
|
||||||
|
@ -58,45 +78,124 @@ constexpr uint32 uint32_max = std::numeric_limits<uint32>::max();
|
||||||
constexpr uint64 uint64_max = std::numeric_limits<uint64>::max();
|
constexpr uint64 uint64_max = std::numeric_limits<uint64>::max();
|
||||||
|
|
||||||
|
|
||||||
typedef float float32;
|
|
||||||
MPT_STATIC_ASSERT(sizeof(float32) == 4);
|
|
||||||
|
|
||||||
typedef double float64;
|
// fp half
|
||||||
MPT_STATIC_ASSERT(sizeof(float64) == 8);
|
// n/a
|
||||||
|
|
||||||
|
// fp single
|
||||||
|
using single = float;
|
||||||
|
constexpr single operator"" _fs(long double lit)
|
||||||
|
{
|
||||||
|
return static_cast<single>(lit);
|
||||||
|
}
|
||||||
|
|
||||||
MPT_STATIC_ASSERT(sizeof(std::uintptr_t) == sizeof(void*));
|
// fp double
|
||||||
|
constexpr double operator"" _fd(long double lit)
|
||||||
|
{
|
||||||
|
return static_cast<double>(lit);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fp extended
|
||||||
|
constexpr long double operator"" _fe(long double lit)
|
||||||
|
{
|
||||||
|
return static_cast<long double>(lit);
|
||||||
|
}
|
||||||
|
|
||||||
MPT_STATIC_ASSERT(std::numeric_limits<unsigned char>::digits == 8);
|
// fp quad
|
||||||
|
// n/a
|
||||||
|
|
||||||
MPT_STATIC_ASSERT(sizeof(char) == 1);
|
using float32 = mpt::select_type<sizeof(float) == 4,
|
||||||
|
float
|
||||||
|
,
|
||||||
|
mpt::select_type<sizeof(double) == 4,
|
||||||
|
double
|
||||||
|
,
|
||||||
|
mpt::select_type<sizeof(long double) == 4,
|
||||||
|
long double
|
||||||
|
,
|
||||||
|
float
|
||||||
|
>::type
|
||||||
|
>::type
|
||||||
|
>::type;
|
||||||
|
constexpr float32 operator"" _f32(long double lit)
|
||||||
|
{
|
||||||
|
return static_cast<float32>(lit);
|
||||||
|
}
|
||||||
|
|
||||||
#if MPT_CXX_AT_LEAST(17)
|
using float64 = mpt::select_type<sizeof(float) == 8,
|
||||||
namespace mpt {
|
float
|
||||||
using byte = std::byte;
|
,
|
||||||
} // namespace mpt
|
mpt::select_type<sizeof(double) == 8,
|
||||||
#define MPT_BYTE_IS_STD_BYTE 1
|
double
|
||||||
|
,
|
||||||
|
mpt::select_type<sizeof(long double) == 8,
|
||||||
|
long double
|
||||||
|
,
|
||||||
|
double
|
||||||
|
>::type
|
||||||
|
>::type
|
||||||
|
>::type;
|
||||||
|
constexpr float64 operator"" _f64(long double lit)
|
||||||
|
{
|
||||||
|
return static_cast<float64>(lit);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace mpt
|
||||||
|
{
|
||||||
|
template <typename T>
|
||||||
|
struct float_traits
|
||||||
|
{
|
||||||
|
static constexpr bool is_float = !std::numeric_limits<T>::is_integer;
|
||||||
|
static constexpr bool is_hard = is_float && !MPT_COMPILER_QUIRK_FLOAT_EMULATED;
|
||||||
|
static constexpr bool is_soft = is_float && MPT_COMPILER_QUIRK_FLOAT_EMULATED;
|
||||||
|
static constexpr bool is_float32 = is_float && (sizeof(T) == 4);
|
||||||
|
static constexpr bool is_float64 = is_float && (sizeof(T) == 8);
|
||||||
|
static constexpr bool is_native_endian = is_float && !MPT_COMPILER_QUIRK_FLOAT_NOTNATIVEENDIAN;
|
||||||
|
static constexpr bool is_ieee754_binary = is_float && std::numeric_limits<T>::is_iec559 && !MPT_COMPILER_QUIRK_FLOAT_NOTIEEE754;
|
||||||
|
static constexpr bool is_ieee754_binary32 = is_float && is_ieee754_binary && is_float32;
|
||||||
|
static constexpr bool is_ieee754_binary64 = is_float && is_ieee754_binary && is_float64;
|
||||||
|
static constexpr bool is_ieee754_binary32ne = is_float && is_ieee754_binary && is_float32 && is_native_endian;
|
||||||
|
static constexpr bool is_ieee754_binary64ne = is_float && is_ieee754_binary && is_float64 && is_native_endian;
|
||||||
|
};
|
||||||
|
} // namespace mpt
|
||||||
|
|
||||||
|
#if MPT_COMPILER_QUIRK_FLOAT_PREFER32
|
||||||
|
using nativefloat = float32;
|
||||||
|
#elif MPT_COMPILER_QUIRK_FLOAT_PREFER64
|
||||||
|
using nativefloat = float64;
|
||||||
#else
|
#else
|
||||||
// In C++11 and C++14, a C++17 compatible definition of byte would not be required to be allowed to alias other types,
|
// prefer smaller floats, but try to use IEEE754 floats
|
||||||
// thus just use a typedef for unsigned char which is guaranteed to be allowed to alias.
|
using nativefloat = mpt::select_type<std::numeric_limits<float>::is_iec559,
|
||||||
//enum class byte : unsigned char { };
|
float
|
||||||
namespace mpt {
|
,
|
||||||
typedef unsigned char byte;
|
mpt::select_type<std::numeric_limits<double>::is_iec559,
|
||||||
} // namespace mpt
|
double
|
||||||
#define MPT_BYTE_IS_STD_BYTE 0
|
,
|
||||||
|
mpt::select_type<std::numeric_limits<long double>::is_iec559,
|
||||||
|
long double
|
||||||
|
,
|
||||||
|
float
|
||||||
|
>::type
|
||||||
|
>::type
|
||||||
|
>::type;
|
||||||
#endif
|
#endif
|
||||||
MPT_STATIC_ASSERT(sizeof(mpt::byte) == 1);
|
constexpr nativefloat operator"" _nf(long double lit)
|
||||||
MPT_STATIC_ASSERT(alignof(mpt::byte) == 1);
|
{
|
||||||
|
return static_cast<nativefloat>(lit);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
namespace mpt {
|
|
||||||
#if MPT_GCC_BEFORE(4,9,0)
|
static_assert(sizeof(std::uintptr_t) == sizeof(void*));
|
||||||
typedef ::max_align_t max_align_t;
|
|
||||||
#else
|
|
||||||
typedef std::max_align_t max_align_t;
|
|
||||||
#endif
|
static_assert(std::numeric_limits<unsigned char>::digits == 8);
|
||||||
} // namespace mpt
|
|
||||||
|
static_assert(sizeof(char) == 1);
|
||||||
|
|
||||||
|
static_assert(sizeof(std::byte) == 1);
|
||||||
|
static_assert(alignof(std::byte) == 1);
|
||||||
|
|
||||||
|
|
||||||
namespace mpt {
|
namespace mpt {
|
||||||
|
@ -104,7 +203,7 @@ constexpr int arch_bits = sizeof(void*) * 8;
|
||||||
constexpr std::size_t pointer_size = sizeof(void*);
|
constexpr std::size_t pointer_size = sizeof(void*);
|
||||||
} // namespace mpt
|
} // namespace mpt
|
||||||
|
|
||||||
MPT_STATIC_ASSERT(mpt::arch_bits == static_cast<int>(mpt::pointer_size) * 8);
|
static_assert(mpt::arch_bits == static_cast<int>(mpt::pointer_size) * 8);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -124,6 +223,14 @@ struct limits
|
||||||
namespace mpt
|
namespace mpt
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#if MPT_CXX_AT_LEAST(20)
|
||||||
|
|
||||||
|
using std::source_location;
|
||||||
|
|
||||||
|
#define MPT_SOURCE_LOCATION_CURRENT() std::source_location::current()
|
||||||
|
|
||||||
|
#else // !C++20
|
||||||
|
|
||||||
// compatible with std::experimental::source_location from Library Fundamentals TS v2.
|
// compatible with std::experimental::source_location from Library Fundamentals TS v2.
|
||||||
struct source_location
|
struct source_location
|
||||||
{
|
{
|
||||||
|
@ -172,7 +279,9 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MPT_SOURCE_LOCATION_CURRENT() mpt::source_location::current( __FILE__ , __FUNCTION__ , __LINE__ , 0 )
|
#define MPT_SOURCE_LOCATION_CURRENT() mpt::source_location::current( __FILE__ , __func__ , __LINE__ , 0 )
|
||||||
|
|
||||||
|
#endif // C++20
|
||||||
|
|
||||||
} // namespace mpt
|
} // namespace mpt
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,10 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#if MPT_COMPILER_MSVC
|
||||||
|
#include <intrin.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
OPENMPT_NAMESPACE_BEGIN
|
OPENMPT_NAMESPACE_BEGIN
|
||||||
|
@ -49,46 +53,66 @@ OPENMPT_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace mpt
|
||||||
|
{
|
||||||
|
template <typename T, std::size_t N, typename Tx>
|
||||||
|
MPT_CONSTEXPR14_FUN std::array<T, N> init_array(const Tx & x)
|
||||||
|
{
|
||||||
|
std::array<T, N> result{};
|
||||||
|
for(std::size_t i = 0; i < N; ++i)
|
||||||
|
{
|
||||||
|
result[i] = x;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
} // namespace mpt
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace mpt
|
||||||
|
{
|
||||||
|
|
||||||
|
// Work-around for the requirement of at least 1 non-throwing function argument combination in C++ (17,2a).
|
||||||
|
|
||||||
|
template <typename Exception>
|
||||||
|
MPT_CONSTEXPR14_FUN bool constexpr_throw_helper(Exception && e, bool really = true)
|
||||||
|
{
|
||||||
|
//return !really ? really : throw std::forward<Exception>(e);
|
||||||
|
if(really)
|
||||||
|
{
|
||||||
|
throw std::forward<Exception>(e);
|
||||||
|
}
|
||||||
|
// cppcheck-suppress identicalConditionAfterEarlyExit
|
||||||
|
return really;
|
||||||
|
}
|
||||||
|
template <typename Exception>
|
||||||
|
MPT_CONSTEXPR14_FUN bool constexpr_throw(Exception && e)
|
||||||
|
{
|
||||||
|
return mpt::constexpr_throw_helper(std::forward<Exception>(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename Exception>
|
||||||
|
constexpr T constexpr_throw_helper(Exception && e, bool really = true)
|
||||||
|
{
|
||||||
|
//return !really ? really : throw std::forward<Exception>(e);
|
||||||
|
if(really)
|
||||||
|
{
|
||||||
|
throw std::forward<Exception>(e);
|
||||||
|
}
|
||||||
|
return T{};
|
||||||
|
}
|
||||||
|
template <typename T, typename Exception>
|
||||||
|
constexpr T constexpr_throw(Exception && e)
|
||||||
|
{
|
||||||
|
return mpt::constexpr_throw_helper<T>(std::forward<Exception>(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mpt
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace mpt {
|
namespace mpt {
|
||||||
|
|
||||||
// GCC 4.5 and up provides templated overloads of std::abs that convert
|
|
||||||
// integer type narrower than int to double.
|
|
||||||
// This is fixed as of GCC 7.1.
|
|
||||||
// As this is apparently valid by the current standard, Library Working Group
|
|
||||||
// Issue #2735 has been filed (see
|
|
||||||
// <https://cplusplus.github.io/LWG/lwg-defects.html#2735>).
|
|
||||||
// In any case, avoid this insanity and provide our own mpt::abs implementation
|
|
||||||
// for signed integer and floating point types.
|
|
||||||
// Note: We stick to a C++98-style implementation only overloading int and
|
|
||||||
// greater types in order to keep promotion rules consistent for narrower types,
|
|
||||||
// which a templated version returning the argument type would not do. OpenMPT
|
|
||||||
// probably assumes this semantic when calling abs(int8) in various places.
|
|
||||||
inline int abs(int x)
|
|
||||||
{
|
|
||||||
return std::abs(x);
|
|
||||||
}
|
|
||||||
inline long abs(long x)
|
|
||||||
{
|
|
||||||
return std::abs(x);
|
|
||||||
}
|
|
||||||
inline long long abs(long long x)
|
|
||||||
{
|
|
||||||
return std::abs(x);
|
|
||||||
}
|
|
||||||
inline float abs(float x)
|
|
||||||
{
|
|
||||||
return std::fabs(x);
|
|
||||||
}
|
|
||||||
inline double abs(double x)
|
|
||||||
{
|
|
||||||
return std::fabs(x);
|
|
||||||
}
|
|
||||||
inline long double abs(long double x)
|
|
||||||
{
|
|
||||||
return std::fabs(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Modulo with more intuitive behaviour for some contexts:
|
// Modulo with more intuitive behaviour for some contexts:
|
||||||
// Instead of being symmetrical around 0, the pattern for positive numbers is repeated in the negative range.
|
// Instead of being symmetrical around 0, the pattern for positive numbers is repeated in the negative range.
|
||||||
// For example, wrapping_modulo(-1, m) == (m - 1).
|
// For example, wrapping_modulo(-1, m) == (m - 1).
|
||||||
|
@ -118,46 +142,46 @@ template <typename Tdst, typename Tsrc>
|
||||||
inline Tdst saturate_cast(Tsrc src)
|
inline Tdst saturate_cast(Tsrc src)
|
||||||
{
|
{
|
||||||
// This code tries not only to obviously avoid overflows but also to avoid signed/unsigned comparison warnings and type truncation warnings (which in fact would be safe here) by explicit casting.
|
// This code tries not only to obviously avoid overflows but also to avoid signed/unsigned comparison warnings and type truncation warnings (which in fact would be safe here) by explicit casting.
|
||||||
STATIC_ASSERT(std::numeric_limits<Tdst>::is_integer);
|
static_assert(std::numeric_limits<Tdst>::is_integer);
|
||||||
STATIC_ASSERT(std::numeric_limits<Tsrc>::is_integer);
|
static_assert(std::numeric_limits<Tsrc>::is_integer);
|
||||||
MPT_CONSTANT_IF(std::numeric_limits<Tdst>::is_signed && std::numeric_limits<Tsrc>::is_signed)
|
if constexpr(std::numeric_limits<Tdst>::is_signed && std::numeric_limits<Tsrc>::is_signed)
|
||||||
{
|
{
|
||||||
MPT_CONSTANT_IF(sizeof(Tdst) >= sizeof(Tsrc))
|
if constexpr(sizeof(Tdst) >= sizeof(Tsrc))
|
||||||
{
|
{
|
||||||
return static_cast<Tdst>(src);
|
return static_cast<Tdst>(src);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
return static_cast<Tdst>(std::max<Tsrc>(static_cast<Tsrc>(std::numeric_limits<Tdst>::min()), std::min<Tsrc>(src, static_cast<Tsrc>(std::numeric_limits<Tdst>::max()))));
|
return static_cast<Tdst>(std::max(static_cast<Tsrc>(std::numeric_limits<Tdst>::min()), std::min(src, static_cast<Tsrc>(std::numeric_limits<Tdst>::max()))));
|
||||||
}
|
}
|
||||||
} else MPT_CONSTANT_IF(!std::numeric_limits<Tdst>::is_signed && !std::numeric_limits<Tsrc>::is_signed)
|
} else if constexpr(!std::numeric_limits<Tdst>::is_signed && !std::numeric_limits<Tsrc>::is_signed)
|
||||||
{
|
{
|
||||||
MPT_CONSTANT_IF(sizeof(Tdst) >= sizeof(Tsrc))
|
if constexpr(sizeof(Tdst) >= sizeof(Tsrc))
|
||||||
{
|
{
|
||||||
return static_cast<Tdst>(src);
|
return static_cast<Tdst>(src);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
return static_cast<Tdst>(std::min<Tsrc>(src, static_cast<Tsrc>(std::numeric_limits<Tdst>::max())));
|
return static_cast<Tdst>(std::min(src, static_cast<Tsrc>(std::numeric_limits<Tdst>::max())));
|
||||||
}
|
}
|
||||||
} else MPT_CONSTANT_IF(std::numeric_limits<Tdst>::is_signed && !std::numeric_limits<Tsrc>::is_signed)
|
} else if constexpr(std::numeric_limits<Tdst>::is_signed && !std::numeric_limits<Tsrc>::is_signed)
|
||||||
{
|
{
|
||||||
MPT_CONSTANT_IF(sizeof(Tdst) > sizeof(Tsrc))
|
if constexpr(sizeof(Tdst) > sizeof(Tsrc))
|
||||||
{
|
{
|
||||||
return static_cast<Tdst>(src);
|
return static_cast<Tdst>(src);
|
||||||
} else MPT_CONSTANT_IF(sizeof(Tdst) == sizeof(Tsrc))
|
} else if constexpr(sizeof(Tdst) == sizeof(Tsrc))
|
||||||
{
|
{
|
||||||
return static_cast<Tdst>(std::min<Tsrc>(src, static_cast<Tsrc>(std::numeric_limits<Tdst>::max())));
|
return static_cast<Tdst>(std::min(src, static_cast<Tsrc>(std::numeric_limits<Tdst>::max())));
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
return static_cast<Tdst>(std::min<Tsrc>(src, static_cast<Tsrc>(std::numeric_limits<Tdst>::max())));
|
return static_cast<Tdst>(std::min(src, static_cast<Tsrc>(std::numeric_limits<Tdst>::max())));
|
||||||
}
|
}
|
||||||
} else // Tdst unsigned, Tsrc signed
|
} else // Tdst unsigned, Tsrc signed
|
||||||
{
|
{
|
||||||
MPT_CONSTANT_IF(sizeof(Tdst) >= sizeof(Tsrc))
|
if constexpr(sizeof(Tdst) >= sizeof(Tsrc))
|
||||||
{
|
{
|
||||||
return static_cast<Tdst>(std::max<Tsrc>(0, src));
|
return static_cast<Tdst>(std::max(static_cast<Tsrc>(0), src));
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
return static_cast<Tdst>(std::max<Tsrc>(0, std::min<Tsrc>(src, static_cast<Tsrc>(std::numeric_limits<Tdst>::max()))));
|
return static_cast<Tdst>(std::max(static_cast<Tsrc>(0), std::min(src, static_cast<Tsrc>(std::numeric_limits<Tdst>::max()))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,11 +189,11 @@ inline Tdst saturate_cast(Tsrc src)
|
||||||
template <typename Tdst>
|
template <typename Tdst>
|
||||||
inline Tdst saturate_cast(double src)
|
inline Tdst saturate_cast(double src)
|
||||||
{
|
{
|
||||||
if(src >= std::numeric_limits<Tdst>::max())
|
if(src >= static_cast<double>(std::numeric_limits<Tdst>::max()))
|
||||||
{
|
{
|
||||||
return std::numeric_limits<Tdst>::max();
|
return std::numeric_limits<Tdst>::max();
|
||||||
}
|
}
|
||||||
if(src <= std::numeric_limits<Tdst>::min())
|
if(src <= static_cast<double>(std::numeric_limits<Tdst>::min()))
|
||||||
{
|
{
|
||||||
return std::numeric_limits<Tdst>::min();
|
return std::numeric_limits<Tdst>::min();
|
||||||
}
|
}
|
||||||
|
@ -179,11 +203,11 @@ inline Tdst saturate_cast(double src)
|
||||||
template <typename Tdst>
|
template <typename Tdst>
|
||||||
inline Tdst saturate_cast(float src)
|
inline Tdst saturate_cast(float src)
|
||||||
{
|
{
|
||||||
if(src >= std::numeric_limits<Tdst>::max())
|
if(src >= static_cast<float>(std::numeric_limits<Tdst>::max()))
|
||||||
{
|
{
|
||||||
return std::numeric_limits<Tdst>::max();
|
return std::numeric_limits<Tdst>::max();
|
||||||
}
|
}
|
||||||
if(src <= std::numeric_limits<Tdst>::min())
|
if(src <= static_cast<float>(std::numeric_limits<Tdst>::min()))
|
||||||
{
|
{
|
||||||
return std::numeric_limits<Tdst>::min();
|
return std::numeric_limits<Tdst>::min();
|
||||||
}
|
}
|
||||||
|
@ -191,51 +215,51 @@ inline Tdst saturate_cast(float src)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
MPT_CONSTEXPR14_FUN std::size_t weight(T val) noexcept
|
|
||||||
{
|
|
||||||
MPT_STATIC_ASSERT(std::numeric_limits<T>::is_integer);
|
|
||||||
typedef typename std::make_unsigned<T>::type Tunsigned;
|
|
||||||
Tunsigned uval = static_cast<Tunsigned>(val);
|
|
||||||
std::size_t result = 0;
|
|
||||||
while(uval > 0)
|
|
||||||
{
|
|
||||||
if(uval & 0x1)
|
|
||||||
{
|
|
||||||
result++;
|
|
||||||
}
|
|
||||||
uval >>= 1;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if MPT_CXX_AT_LEAST(20)
|
#if MPT_CXX_AT_LEAST(20)
|
||||||
|
|
||||||
using std::ispow2;
|
using std::popcount;
|
||||||
using std::ceil2;
|
using std::has_single_bit;
|
||||||
using std::floor2;
|
using std::bit_ceil;
|
||||||
using std::log2p1;
|
using std::bit_floor;
|
||||||
|
using std::bit_width;
|
||||||
|
using std::rotl;
|
||||||
|
using std::rotr;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
// C++20 <bit> header.
|
// C++20 <bit> header.
|
||||||
// Note that we do not use SFINAE here but instead rely on static_assert.
|
// Note that we do not use SFINAE here but instead rely on static_assert.
|
||||||
// Also note that for C++11 compilers, these functions are not constexpr.
|
|
||||||
// They could be implemented recursively to make them C++11 constexpr compatible if needed.
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
MPT_CONSTEXPR14_FUN bool ispow2(T x) noexcept
|
MPT_CONSTEXPR14_FUN int popcount(T val) noexcept
|
||||||
{
|
{
|
||||||
MPT_STATIC_ASSERT(std::numeric_limits<T>::is_integer);
|
static_assert(std::numeric_limits<T>::is_integer);
|
||||||
MPT_STATIC_ASSERT(std::is_unsigned<T>::value);
|
static_assert(std::is_unsigned<T>::value);
|
||||||
return mpt::weight(x) == 1;
|
int result = 0;
|
||||||
|
while(val > 0)
|
||||||
|
{
|
||||||
|
if(val & 0x1)
|
||||||
|
{
|
||||||
|
result++;
|
||||||
|
}
|
||||||
|
val >>= 1;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
MPT_CONSTEXPR14_FUN T ceil2(T x) noexcept
|
MPT_CONSTEXPR14_FUN bool has_single_bit(T x) noexcept
|
||||||
{
|
{
|
||||||
MPT_STATIC_ASSERT(std::numeric_limits<T>::is_integer);
|
static_assert(std::numeric_limits<T>::is_integer);
|
||||||
MPT_STATIC_ASSERT(std::is_unsigned<T>::value);
|
static_assert(std::is_unsigned<T>::value);
|
||||||
|
return mpt::popcount(x) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
MPT_CONSTEXPR14_FUN T bit_ceil(T x) noexcept
|
||||||
|
{
|
||||||
|
static_assert(std::numeric_limits<T>::is_integer);
|
||||||
|
static_assert(std::is_unsigned<T>::value);
|
||||||
T result = 1;
|
T result = 1;
|
||||||
while(result < x)
|
while(result < x)
|
||||||
{
|
{
|
||||||
|
@ -250,10 +274,10 @@ MPT_CONSTEXPR14_FUN T ceil2(T x) noexcept
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
MPT_CONSTEXPR14_FUN T floor2(T x) noexcept
|
MPT_CONSTEXPR14_FUN T bit_floor(T x) noexcept
|
||||||
{
|
{
|
||||||
MPT_STATIC_ASSERT(std::numeric_limits<T>::is_integer);
|
static_assert(std::numeric_limits<T>::is_integer);
|
||||||
MPT_STATIC_ASSERT(std::is_unsigned<T>::value);
|
static_assert(std::is_unsigned<T>::value);
|
||||||
if(x == 0)
|
if(x == 0)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -272,10 +296,10 @@ MPT_CONSTEXPR14_FUN T floor2(T x) noexcept
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
MPT_CONSTEXPR14_FUN T log2p1(T x) noexcept
|
MPT_CONSTEXPR14_FUN T bit_width(T x) noexcept
|
||||||
{
|
{
|
||||||
MPT_STATIC_ASSERT(std::numeric_limits<T>::is_integer);
|
static_assert(std::numeric_limits<T>::is_integer);
|
||||||
MPT_STATIC_ASSERT(std::is_unsigned<T>::value);
|
static_assert(std::is_unsigned<T>::value);
|
||||||
T result = 0;
|
T result = 0;
|
||||||
while(x > 0)
|
while(x > 0)
|
||||||
{
|
{
|
||||||
|
@ -285,58 +309,50 @@ MPT_CONSTEXPR14_FUN T log2p1(T x) noexcept
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
MPT_CONSTEXPR14_FUN T rotl(T x, int r) noexcept
|
||||||
|
{
|
||||||
|
auto N = std::numeric_limits<T>::digits;
|
||||||
|
return (x >> (N - r)) | (x << r);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
MPT_CONSTEXPR14_FUN T rotr(T x, int r) noexcept
|
||||||
|
{
|
||||||
|
auto N = std::numeric_limits<T>::digits;
|
||||||
|
return (x << (N - r)) | (x >> r);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
MPT_CONSTEXPR14_FUN T rotl(T x, int s) noexcept
|
||||||
|
{
|
||||||
|
static_assert(std::numeric_limits<T>::is_integer);
|
||||||
|
static_assert(std::is_unsigned<T>::value);
|
||||||
|
auto N = std::numeric_limits<T>::digits;
|
||||||
|
auto r = s % N;
|
||||||
|
return (s < 0) ? detail::rotr(x, -s) : ((x >> (N - r)) | (x << r));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
MPT_CONSTEXPR14_FUN T rotr(T x, int s) noexcept
|
||||||
|
{
|
||||||
|
static_assert(std::numeric_limits<T>::is_integer);
|
||||||
|
static_assert(std::is_unsigned<T>::value);
|
||||||
|
auto N = std::numeric_limits<T>::digits;
|
||||||
|
auto r = s % N;
|
||||||
|
return (s < 0) ? detail::rotl(x, -s) : ((x << (N - r)) | (x >> r));
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} // namespace mpt
|
} // namespace mpt
|
||||||
|
|
||||||
|
|
||||||
#if defined(MODPLUG_TRACKER)
|
|
||||||
// Tracker code requires MIN/MAX to work in constexpr contexts.
|
|
||||||
// We could make MIN/MAX constexpr for supporting compilers,
|
|
||||||
// but that would just needlessly complicate the support matrix
|
|
||||||
// for now.
|
|
||||||
#ifndef MPT_MINMAX_MACROS
|
|
||||||
#define MPT_MINMAX_MACROS
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if MPT_COMPILER_MSVC
|
|
||||||
// MSVC disables a bunch of type conversion warnings once a macro is involved.
|
|
||||||
// Replacing the macro with a template thus spews a TON OF WARNINGS for now.
|
|
||||||
#ifndef MPT_MINMAX_MACROS
|
|
||||||
#define MPT_MINMAX_MACROS
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MPT_MINMAX_MACROS)
|
|
||||||
|
|
||||||
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
|
|
||||||
|
|
||||||
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
namespace mpt { namespace Legacy {
|
|
||||||
|
|
||||||
template <typename Ta, typename Tb>
|
|
||||||
MPT_FORCEINLINE auto MAX(const Ta &a, const Tb &b) -> decltype((a>b)?a:b)
|
|
||||||
{
|
|
||||||
return (a > b) ? a : b;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Ta, typename Tb>
|
|
||||||
MPT_FORCEINLINE auto MIN(const Ta &a, const Tb &b) -> decltype((a<b)?a:b)
|
|
||||||
{
|
|
||||||
return (a < b) ? a : b;
|
|
||||||
}
|
|
||||||
|
|
||||||
} } // namespace mpt::Legacy
|
|
||||||
|
|
||||||
using namespace mpt::Legacy;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
namespace Util
|
namespace Util
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -348,10 +364,10 @@ struct ModIfNotZeroImpl
|
||||||
template <typename Tval>
|
template <typename Tval>
|
||||||
inline Tval mod(Tval x)
|
inline Tval mod(Tval x)
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(std::numeric_limits<Tmod>::is_integer);
|
static_assert(std::numeric_limits<Tmod>::is_integer);
|
||||||
STATIC_ASSERT(!std::numeric_limits<Tmod>::is_signed);
|
static_assert(!std::numeric_limits<Tmod>::is_signed);
|
||||||
STATIC_ASSERT(std::numeric_limits<Tval>::is_integer);
|
static_assert(std::numeric_limits<Tval>::is_integer);
|
||||||
STATIC_ASSERT(!std::numeric_limits<Tval>::is_signed);
|
static_assert(!std::numeric_limits<Tval>::is_signed);
|
||||||
return static_cast<Tval>(x % m);
|
return static_cast<Tval>(x % m);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -389,8 +405,8 @@ inline T ExponentialGrow(const T &x, const Tlimit &limit)
|
||||||
{
|
{
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
T add = std::min<T>(x >> 1, std::numeric_limits<T>::max() - x);
|
T add = std::min(x >> 1, std::numeric_limits<T>::max() - x);
|
||||||
return std::min<T>(x + add, mpt::saturate_cast<T>(limit));
|
return std::min(x + add, mpt::saturate_cast<T>(limit));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -402,34 +418,6 @@ inline T ExponentialGrow(const T &x)
|
||||||
} //namespace Util
|
} //namespace Util
|
||||||
|
|
||||||
|
|
||||||
namespace mpt
|
|
||||||
{
|
|
||||||
|
|
||||||
// C++17 clamp
|
|
||||||
|
|
||||||
#if MPT_CXX_AT_LEAST(17)
|
|
||||||
|
|
||||||
using std::clamp;
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
template<typename T, typename Compare>
|
|
||||||
MPT_CONSTEXPR11_FUN const T & clamp(const T & v, const T & lo, const T & hi, Compare comp)
|
|
||||||
{
|
|
||||||
return comp(v, lo) ? lo : comp(hi, v) ? hi : v;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
MPT_CONSTEXPR11_FUN const T & clamp(const T & v, const T & lo, const T & hi)
|
|
||||||
{
|
|
||||||
return mpt::clamp(v, lo, hi, std::less<T>());
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace mpt
|
|
||||||
|
|
||||||
|
|
||||||
// Limits 'val' to given range. If 'val' is less than 'lowerLimit', 'val' is set to value 'lowerLimit'.
|
// Limits 'val' to given range. If 'val' is less than 'lowerLimit', 'val' is set to value 'lowerLimit'.
|
||||||
// Similarly if 'val' is greater than 'upperLimit', 'val' is set to value 'upperLimit'.
|
// Similarly if 'val' is greater than 'upperLimit', 'val' is set to value 'upperLimit'.
|
||||||
// If 'lowerLimit' > 'upperLimit', 'val' won't be modified.
|
// If 'lowerLimit' > 'upperLimit', 'val' won't be modified.
|
||||||
|
@ -489,8 +477,8 @@ namespace mpt
|
||||||
template <typename T>
|
template <typename T>
|
||||||
MPT_FORCEINLINE auto rshift_signed_standard(T x, int y) -> decltype(x >> y)
|
MPT_FORCEINLINE auto rshift_signed_standard(T x, int y) -> decltype(x >> y)
|
||||||
{
|
{
|
||||||
MPT_STATIC_ASSERT(std::numeric_limits<T>::is_integer);
|
static_assert(std::numeric_limits<T>::is_integer);
|
||||||
MPT_STATIC_ASSERT(std::numeric_limits<T>::is_signed);
|
static_assert(std::numeric_limits<T>::is_signed);
|
||||||
typedef decltype(x >> y) result_type;
|
typedef decltype(x >> y) result_type;
|
||||||
typedef typename std::make_unsigned<result_type>::type unsigned_result_type;
|
typedef typename std::make_unsigned<result_type>::type unsigned_result_type;
|
||||||
const unsigned_result_type roffset = static_cast<unsigned_result_type>(1) << ((sizeof(result_type) * 8) - 1);
|
const unsigned_result_type roffset = static_cast<unsigned_result_type>(1) << ((sizeof(result_type) * 8) - 1);
|
||||||
|
@ -505,8 +493,8 @@ MPT_FORCEINLINE auto rshift_signed_standard(T x, int y) -> decltype(x >> y)
|
||||||
template <typename T>
|
template <typename T>
|
||||||
MPT_FORCEINLINE auto lshift_signed_standard(T x, int y) -> decltype(x << y)
|
MPT_FORCEINLINE auto lshift_signed_standard(T x, int y) -> decltype(x << y)
|
||||||
{
|
{
|
||||||
MPT_STATIC_ASSERT(std::numeric_limits<T>::is_integer);
|
static_assert(std::numeric_limits<T>::is_integer);
|
||||||
MPT_STATIC_ASSERT(std::numeric_limits<T>::is_signed);
|
static_assert(std::numeric_limits<T>::is_signed);
|
||||||
typedef decltype(x << y) result_type;
|
typedef decltype(x << y) result_type;
|
||||||
typedef typename std::make_unsigned<result_type>::type unsigned_result_type;
|
typedef typename std::make_unsigned<result_type>::type unsigned_result_type;
|
||||||
const unsigned_result_type roffset = static_cast<unsigned_result_type>(1) << ((sizeof(result_type) * 8) - 1);
|
const unsigned_result_type roffset = static_cast<unsigned_result_type>(1) << ((sizeof(result_type) * 8) - 1);
|
||||||
|
@ -523,16 +511,16 @@ MPT_FORCEINLINE auto lshift_signed_standard(T x, int y) -> decltype(x << y)
|
||||||
template <typename T>
|
template <typename T>
|
||||||
MPT_FORCEINLINE auto rshift_signed_undefined(T x, int y) -> decltype(x >> y)
|
MPT_FORCEINLINE auto rshift_signed_undefined(T x, int y) -> decltype(x >> y)
|
||||||
{
|
{
|
||||||
MPT_STATIC_ASSERT(std::numeric_limits<T>::is_integer);
|
static_assert(std::numeric_limits<T>::is_integer);
|
||||||
MPT_STATIC_ASSERT(std::numeric_limits<T>::is_signed);
|
static_assert(std::numeric_limits<T>::is_signed);
|
||||||
return x >> y;
|
return x >> y;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
MPT_FORCEINLINE auto lshift_signed_undefined(T x, int y) -> decltype(x << y)
|
MPT_FORCEINLINE auto lshift_signed_undefined(T x, int y) -> decltype(x << y)
|
||||||
{
|
{
|
||||||
MPT_STATIC_ASSERT(std::numeric_limits<T>::is_integer);
|
static_assert(std::numeric_limits<T>::is_integer);
|
||||||
MPT_STATIC_ASSERT(std::numeric_limits<T>::is_signed);
|
static_assert(std::numeric_limits<T>::is_signed);
|
||||||
return x << y;
|
return x << y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -564,9 +552,22 @@ MPT_FORCEINLINE auto lshift_signed(T x, int y) -> decltype(x << y)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} // namespace mpt
|
template<typename>
|
||||||
|
struct array_size;
|
||||||
|
|
||||||
|
template <typename T, std::size_t N>
|
||||||
|
struct array_size<std::array<T, N>>
|
||||||
|
{
|
||||||
|
static constexpr std::size_t size = N;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, std::size_t N>
|
||||||
|
struct array_size<T[N]>
|
||||||
|
{
|
||||||
|
static constexpr std::size_t size = N;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mpt
|
||||||
|
|
||||||
namespace Util
|
namespace Util
|
||||||
{
|
{
|
||||||
|
@ -574,8 +575,7 @@ namespace Util
|
||||||
// Returns maximum value of given integer type.
|
// Returns maximum value of given integer type.
|
||||||
template <class T> constexpr T MaxValueOfType(const T&) {static_assert(std::numeric_limits<T>::is_integer == true, "Only integer types are allowed."); return (std::numeric_limits<T>::max)();}
|
template <class T> constexpr T MaxValueOfType(const T&) {static_assert(std::numeric_limits<T>::is_integer == true, "Only integer types are allowed."); return (std::numeric_limits<T>::max)();}
|
||||||
|
|
||||||
}
|
} // namespace Util
|
||||||
|
|
||||||
|
|
||||||
namespace mpt
|
namespace mpt
|
||||||
{
|
{
|
||||||
|
@ -677,58 +677,4 @@ namespace Util {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace mpt
|
|
||||||
{
|
|
||||||
|
|
||||||
#if MPT_CXX_AT_LEAST(17)
|
|
||||||
|
|
||||||
using std::gcd;
|
|
||||||
using std::lcm;
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
// Greatest Common Divisor. Always returns non-negative number.
|
|
||||||
// compatible with C++17 std::gcd
|
|
||||||
template <typename A, typename B>
|
|
||||||
inline typename std::common_type<A, B>::type gcd(A a_, B b_)
|
|
||||||
{
|
|
||||||
typename std::common_type<A, B>::type a = a_;
|
|
||||||
typename std::common_type<A, B>::type b = b_;
|
|
||||||
if(a < 0)
|
|
||||||
a = -a;
|
|
||||||
if(b < 0)
|
|
||||||
b = -b;
|
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
if(a == 0)
|
|
||||||
return b;
|
|
||||||
b %= a;
|
|
||||||
if(b == 0)
|
|
||||||
return a;
|
|
||||||
a %= b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Least Common Multiple. Always returns non-negative number.
|
|
||||||
// compatible with C++17 std::lcm
|
|
||||||
template <typename A, typename B>
|
|
||||||
inline typename std::common_type<A, B>::type lcm(A a_, B b_)
|
|
||||||
{
|
|
||||||
typename std::common_type<A, B>::type a = a_;
|
|
||||||
typename std::common_type<A, B>::type b = b_;
|
|
||||||
if(a < 0)
|
|
||||||
a = -a;
|
|
||||||
if(b < 0)
|
|
||||||
b = -b;
|
|
||||||
if((a | b) == 0)
|
|
||||||
return 0;
|
|
||||||
return a / mpt::gcd(a, b) * b;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace mpt
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
OPENMPT_NAMESPACE_END
|
OPENMPT_NAMESPACE_END
|
||||||
|
|
|
@ -1,177 +0,0 @@
|
||||||
/*
|
|
||||||
* mptBufferIO.h
|
|
||||||
* -------------
|
|
||||||
* Purpose: A wrapper around std::stringstream, fixing MSVC tell/seek problems with empty streams.
|
|
||||||
* Notes : You should only ever use these wrappers instead of plain std::stringstream classes.
|
|
||||||
* Authors: OpenMPT Devs
|
|
||||||
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "BuildSettings.h"
|
|
||||||
|
|
||||||
#include <ios>
|
|
||||||
#include <istream>
|
|
||||||
#include <ostream>
|
|
||||||
#include <sstream>
|
|
||||||
#include <streambuf>
|
|
||||||
|
|
||||||
OPENMPT_NAMESPACE_BEGIN
|
|
||||||
|
|
||||||
|
|
||||||
// MSVC std::stringbuf (and thereby std::ostringstream, std::istringstream and
|
|
||||||
// std::stringstream) fail seekpos() and seekoff() when the stringbuf is
|
|
||||||
// currently empty.
|
|
||||||
// seekpos() and seekoff() can get called via tell*() or seek*() iostream
|
|
||||||
// members. seekoff() (and thereby tell*()), but not seekpos(), has been fixed
|
|
||||||
// from VS2010 onwards to handle this specific case and changed to not fail
|
|
||||||
// when the stringbuf is empty.
|
|
||||||
// Work-around strategy:
|
|
||||||
// As re-implementing or duplicating the whole std::stringbuf semantics would be
|
|
||||||
// rather convoluted, we make use of the knowledge of specific inner workings of
|
|
||||||
// the MSVC implementation here and just fix-up where it causes problems. This
|
|
||||||
// keeps the additional code at a minimum size.
|
|
||||||
|
|
||||||
|
|
||||||
namespace mpt
|
|
||||||
{
|
|
||||||
|
|
||||||
#ifdef MPT_COMPILER_QUIRK_MSVC_STRINGSTREAM
|
|
||||||
|
|
||||||
class stringbuf
|
|
||||||
: public std::stringbuf
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
stringbuf(std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
|
|
||||||
: std::stringbuf(mode)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
stringbuf(const std::string &str, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
|
|
||||||
: std::stringbuf(str, mode)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
virtual pos_type seekoff(off_type off, std::ios_base::seekdir way, std::ios_base::openmode which = std::ios_base::in | std::ios_base::out)
|
|
||||||
{
|
|
||||||
pos_type result = std::stringbuf::seekoff(off, way, which);
|
|
||||||
if(result == pos_type(-1))
|
|
||||||
{
|
|
||||||
if((which & std::ios_base::in) || (which & std::ios_base::out))
|
|
||||||
{
|
|
||||||
if(off == 0)
|
|
||||||
{
|
|
||||||
result = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
virtual pos_type seekpos(pos_type ptr, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
|
|
||||||
{
|
|
||||||
pos_type result = std::stringbuf::seekpos(ptr, mode);
|
|
||||||
if(result == pos_type(-1))
|
|
||||||
{
|
|
||||||
if((mode & std::ios_base::in) || (mode & std::ios_base::out))
|
|
||||||
{
|
|
||||||
if(static_cast<std::streamoff>(ptr) == 0)
|
|
||||||
{
|
|
||||||
result = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class istringstream
|
|
||||||
: public std::basic_istream<char>
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
mpt::stringbuf buf;
|
|
||||||
public:
|
|
||||||
istringstream(std::ios_base::openmode mode = std::ios_base::in)
|
|
||||||
: std::basic_istream<char>(&buf)
|
|
||||||
, buf(mode | std::ios_base::in)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
istringstream(const std::string &str, std::ios_base::openmode mode = std::ios_base::in)
|
|
||||||
: std::basic_istream<char>(&buf)
|
|
||||||
, buf(str, mode | std::ios_base::in)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
~istringstream()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
mpt::stringbuf *rdbuf() const { return const_cast<mpt::stringbuf*>(&buf); }
|
|
||||||
std::string str() const { return buf.str(); }
|
|
||||||
void str(const std::string &str) { buf.str(str); }
|
|
||||||
};
|
|
||||||
|
|
||||||
class ostringstream
|
|
||||||
: public std::basic_ostream<char>
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
mpt::stringbuf buf;
|
|
||||||
public:
|
|
||||||
ostringstream(std::ios_base::openmode mode = std::ios_base::out)
|
|
||||||
: std::basic_ostream<char>(&buf)
|
|
||||||
, buf(mode | std::ios_base::out)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
ostringstream(const std::string &str, std::ios_base::openmode mode = std::ios_base::out)
|
|
||||||
: std::basic_ostream<char>(&buf)
|
|
||||||
, buf(str, mode | std::ios_base::out)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
~ostringstream()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
mpt::stringbuf *rdbuf() const { return const_cast<mpt::stringbuf*>(&buf); }
|
|
||||||
std::string str() const { return buf.str(); }
|
|
||||||
void str(const std::string &str) { buf.str(str); }
|
|
||||||
};
|
|
||||||
|
|
||||||
class stringstream
|
|
||||||
: public std::basic_iostream<char>
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
mpt::stringbuf buf;
|
|
||||||
public:
|
|
||||||
stringstream(std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
|
|
||||||
: std::basic_iostream<char>(&buf)
|
|
||||||
, buf(mode | std::ios_base::in | std::ios_base::out)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
stringstream(const std::string &str, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
|
|
||||||
: std::basic_iostream<char>(&buf)
|
|
||||||
, buf(str, mode | std::ios_base::in | std::ios_base::out)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
~stringstream()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
mpt::stringbuf *rdbuf() const { return const_cast<mpt::stringbuf*>(&buf); }
|
|
||||||
std::string str() const { return buf.str(); }
|
|
||||||
void str(const std::string &str) { buf.str(str); }
|
|
||||||
};
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
typedef std::stringbuf stringbuf;
|
|
||||||
typedef std::istringstream istringstream;
|
|
||||||
typedef std::ostringstream ostringstream;
|
|
||||||
typedef std::stringstream stringstream;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace mpt
|
|
||||||
|
|
||||||
|
|
||||||
OPENMPT_NAMESPACE_END
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ uint8 ProcModel = 0;
|
||||||
uint8 ProcStepping = 0;
|
uint8 ProcStepping = 0;
|
||||||
|
|
||||||
|
|
||||||
#if MPT_COMPILER_MSVC && (defined(ENABLE_X86) || defined(ENABLE_X64))
|
#if MPT_COMPILER_MSVC && (defined(ENABLE_X86) || defined(ENABLE_X64)) && defined(ENABLE_CPUID)
|
||||||
|
|
||||||
|
|
||||||
#include <intrin.h>
|
#include <intrin.h>
|
||||||
|
@ -97,42 +97,25 @@ static cpuid_result cpuid(uint32 function)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
|
|
||||||
static cpuid_result cpuidex(uint32 function_a, uint32 function_c)
|
|
||||||
{
|
|
||||||
cpuid_result result;
|
|
||||||
int CPUInfo[4];
|
|
||||||
__cpuidex(CPUInfo, function_a, function_c);
|
|
||||||
result.a = CPUInfo[0];
|
|
||||||
result.b = CPUInfo[1];
|
|
||||||
result.c = CPUInfo[2];
|
|
||||||
result.d = CPUInfo[3];
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
void InitProcSupport()
|
void InitProcSupport()
|
||||||
{
|
{
|
||||||
|
|
||||||
RealProcSupport = 0;
|
RealProcSupport = 0;
|
||||||
ProcSupport = 0;
|
ProcSupport = 0;
|
||||||
MemsetZero(ProcVendorID);
|
mpt::String::WriteAutoBuf(ProcVendorID) = "";
|
||||||
MemsetZero(ProcBrandID);
|
mpt::String::WriteAutoBuf(ProcBrandID) = "";
|
||||||
ProcFamily = 0;
|
ProcFamily = 0;
|
||||||
ProcModel = 0;
|
ProcModel = 0;
|
||||||
ProcStepping = 0;
|
ProcStepping = 0;
|
||||||
|
|
||||||
|
ProcSupport |= PROCSUPPORT_ASM_INTRIN;
|
||||||
|
ProcSupport |= PROCSUPPORT_CPUID;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
cpuid_result VendorString = cpuid(0x00000000u);
|
cpuid_result VendorString = cpuid(0x00000000u);
|
||||||
mpt::String::WriteAutoBuf(ProcVendorID) = VendorString.as_string();
|
mpt::String::WriteAutoBuf(ProcVendorID) = VendorString.as_string();
|
||||||
|
if(VendorString.a >= 0x00000001u)
|
||||||
// Cyrix 6x86 and 6x86MX do not specify the value returned in eax.
|
|
||||||
// They both support 0x00000001u however.
|
|
||||||
if((VendorString.as_string() == "CyrixInstead") || (VendorString.a >= 0x00000001u))
|
|
||||||
{
|
{
|
||||||
cpuid_result StandardFeatureFlags = cpuid(0x00000001u);
|
cpuid_result StandardFeatureFlags = cpuid(0x00000001u);
|
||||||
uint32 Stepping = (StandardFeatureFlags.a >> 0) & 0x0f;
|
uint32 Stepping = (StandardFeatureFlags.a >> 0) & 0x0f;
|
||||||
|
@ -140,40 +123,21 @@ void InitProcSupport()
|
||||||
uint32 BaseFamily = (StandardFeatureFlags.a >> 8) & 0x0f;
|
uint32 BaseFamily = (StandardFeatureFlags.a >> 8) & 0x0f;
|
||||||
uint32 ExtModel = (StandardFeatureFlags.a >> 16) & 0x0f;
|
uint32 ExtModel = (StandardFeatureFlags.a >> 16) & 0x0f;
|
||||||
uint32 ExtFamily = (StandardFeatureFlags.a >> 20) & 0xff;
|
uint32 ExtFamily = (StandardFeatureFlags.a >> 20) & 0xff;
|
||||||
if(VendorString.as_string() == "GenuineIntel")
|
if(BaseFamily == 0xf)
|
||||||
{
|
{
|
||||||
if(BaseFamily == 0xf)
|
ProcFamily = static_cast<uint16>(ExtFamily + BaseFamily);
|
||||||
{
|
|
||||||
ProcFamily = static_cast<uint16>(ExtFamily + BaseFamily);
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
ProcFamily = static_cast<uint16>(BaseFamily);
|
|
||||||
}
|
|
||||||
if(BaseFamily == 0x6 || BaseFamily == 0xf)
|
|
||||||
{
|
|
||||||
ProcModel = static_cast<uint8>((ExtModel << 4) | (BaseModel << 0));
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
ProcModel = static_cast<uint8>(BaseModel);
|
|
||||||
}
|
|
||||||
} else if(VendorString.as_string() == "AuthenticAMD")
|
|
||||||
{
|
|
||||||
if(BaseFamily == 0xf)
|
|
||||||
{
|
|
||||||
ProcFamily = static_cast<uint16>(ExtFamily + BaseFamily);
|
|
||||||
ProcModel = static_cast<uint8>((ExtModel << 4) | (BaseModel << 0));
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
ProcFamily = static_cast<uint16>(BaseFamily);
|
|
||||||
ProcModel = static_cast<uint8>(BaseModel);
|
|
||||||
}
|
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
ProcFamily = static_cast<uint16>(BaseFamily);
|
ProcFamily = static_cast<uint16>(BaseFamily);
|
||||||
|
}
|
||||||
|
if((BaseFamily == 0x6) || (BaseFamily == 0xf))
|
||||||
|
{
|
||||||
|
ProcModel = static_cast<uint8>((ExtModel << 4) | (BaseModel << 0));
|
||||||
|
} else
|
||||||
|
{
|
||||||
ProcModel = static_cast<uint8>(BaseModel);
|
ProcModel = static_cast<uint8>(BaseModel);
|
||||||
}
|
}
|
||||||
ProcStepping = static_cast<uint8>(Stepping);
|
ProcStepping = static_cast<uint8>(Stepping);
|
||||||
if(StandardFeatureFlags.d & (1<<15)) ProcSupport |= PROCSUPPORT_CMOV;
|
|
||||||
if(StandardFeatureFlags.d & (1<<23)) ProcSupport |= PROCSUPPORT_MMX;
|
if(StandardFeatureFlags.d & (1<<23)) ProcSupport |= PROCSUPPORT_MMX;
|
||||||
if(StandardFeatureFlags.d & (1<<25)) ProcSupport |= PROCSUPPORT_SSE;
|
if(StandardFeatureFlags.d & (1<<25)) ProcSupport |= PROCSUPPORT_SSE;
|
||||||
if(StandardFeatureFlags.d & (1<<26)) ProcSupport |= PROCSUPPORT_SSE2;
|
if(StandardFeatureFlags.d & (1<<26)) ProcSupport |= PROCSUPPORT_SSE2;
|
||||||
|
@ -181,115 +145,56 @@ void InitProcSupport()
|
||||||
if(StandardFeatureFlags.c & (1<< 9)) ProcSupport |= PROCSUPPORT_SSSE3;
|
if(StandardFeatureFlags.c & (1<< 9)) ProcSupport |= PROCSUPPORT_SSSE3;
|
||||||
if(StandardFeatureFlags.c & (1<<19)) ProcSupport |= PROCSUPPORT_SSE4_1;
|
if(StandardFeatureFlags.c & (1<<19)) ProcSupport |= PROCSUPPORT_SSE4_1;
|
||||||
if(StandardFeatureFlags.c & (1<<20)) ProcSupport |= PROCSUPPORT_SSE4_2;
|
if(StandardFeatureFlags.c & (1<<20)) ProcSupport |= PROCSUPPORT_SSE4_2;
|
||||||
|
if(StandardFeatureFlags.c & (1<<28)) ProcSupport |= PROCSUPPORT_AVX;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool canExtended = false;
|
cpuid_result ExtendedVendorString = cpuid(0x80000000u);
|
||||||
// 3DNow! manual recommends to just execute 0x80000000u.
|
if(ExtendedVendorString.a >= 0x80000001u)
|
||||||
// It is totally unknown how earlier CPUs from other vendors
|
|
||||||
// would behave.
|
|
||||||
// Thus we only execute 0x80000000u on other vendors CPUs for the earliest
|
|
||||||
// that we found it documented for and that actually supports 3DNow!.
|
|
||||||
// We only need 0x80000000u in order to detect 3DNow!.
|
|
||||||
// Thus, this is enough for us.
|
|
||||||
if(VendorString.as_string() == "GenuineIntel")
|
|
||||||
{ // Intel
|
|
||||||
|
|
||||||
// 5.9.x : Quark
|
|
||||||
// 6.11.x: P3-S (Tualatin)
|
|
||||||
if((ProcFamily > 6) || ((ProcFamily == 6) && (ProcModel >= 11)) || ((ProcFamily == 5) && (ProcModel >= 9)))
|
|
||||||
{
|
|
||||||
canExtended = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if((VendorString.as_string() == "AuthenticAMD") || (VendorString.as_string() == "AMDisbetter!"))
|
|
||||||
{ // AMD
|
|
||||||
|
|
||||||
if((ProcFamily > 5) || ((ProcFamily == 5) && (ProcModel >= 8)))
|
|
||||||
{ // >= K6-2 (K6 = Family 5, K6-2 = Model 8)
|
|
||||||
// Not sure if earlier AMD CPUs support 0x80000000u.
|
|
||||||
// AMD 5k86 and AMD K5 manuals do not mention it.
|
|
||||||
canExtended = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if(VendorString.as_string() == "CentaurHauls")
|
|
||||||
{ // Centaur (IDT WinChip or VIA C3)
|
|
||||||
|
|
||||||
if(ProcFamily == 5)
|
|
||||||
{ // IDT
|
|
||||||
|
|
||||||
if(ProcModel >= 8)
|
|
||||||
{ // >= WinChip 2
|
|
||||||
canExtended = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if(ProcFamily >= 6)
|
|
||||||
{ // VIA
|
|
||||||
|
|
||||||
if((ProcFamily >= 7) || ((ProcFamily == 6) && (ProcModel >= 7)))
|
|
||||||
{ // >= C3 Samuel 2
|
|
||||||
canExtended = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if(VendorString.as_string() == "CyrixInstead")
|
|
||||||
{ // Cyrix
|
|
||||||
|
|
||||||
// 6x86 : 5.2.x
|
|
||||||
// 6x86L : 5.2.x
|
|
||||||
// MediaGX : 4.4.x
|
|
||||||
// 6x86MX : 6.0.x
|
|
||||||
// MII : 6.0.x
|
|
||||||
// MediaGXm: 5.4.x
|
|
||||||
// well, doh ...
|
|
||||||
|
|
||||||
if((ProcFamily == 5) && (ProcModel >= 4))
|
|
||||||
{ // Cyrix MediaGXm
|
|
||||||
canExtended = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if(VendorString.as_string() == "Geode by NSC")
|
|
||||||
{ // National Semiconductor
|
|
||||||
|
|
||||||
if((ProcFamily > 5) || ((ProcFamily == 5) && (ProcModel >= 5)))
|
|
||||||
{ // >= Geode GX2
|
|
||||||
canExtended = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else
|
|
||||||
{ // unknown, which nowadays most likely means some virtualized CPU
|
|
||||||
|
|
||||||
// we assume extended flags present in this case
|
|
||||||
canExtended = true;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if(canExtended)
|
|
||||||
{
|
{
|
||||||
cpuid_result ExtendedVendorString = cpuid(0x80000000u);
|
cpuid_result ExtendedFeatureFlags = cpuid(0x80000001u);
|
||||||
if(ExtendedVendorString.a >= 0x80000001u)
|
if(ExtendedFeatureFlags.d & (1<<29)) ProcSupport |= PROCSUPPORT_LM;
|
||||||
|
}
|
||||||
|
if(ExtendedVendorString.a >= 0x80000004u)
|
||||||
|
{
|
||||||
|
mpt::String::WriteAutoBuf(ProcBrandID) = cpuid(0x80000002u).as_string4() + cpuid(0x80000003u).as_string4() + cpuid(0x80000004u).as_string4();
|
||||||
|
if(ExtendedVendorString.a >= 0x80000007u)
|
||||||
{
|
{
|
||||||
cpuid_result ExtendedFeatureFlags = cpuid(0x80000001u);
|
cpuid_result ExtendedFeatures = cpuid(0x80000007u);
|
||||||
if(ExtendedFeatureFlags.d & (1<<29)) ProcSupport |= PROCSUPPORT_LM;
|
if(ExtendedFeatures.b & (1<< 5)) ProcSupport |= PROCSUPPORT_AVX2;
|
||||||
if((VendorString.as_string() == "AuthenticAMD") || (VendorString.as_string() == "AMDisbetter!"))
|
|
||||||
{
|
|
||||||
if(ExtendedFeatureFlags.d & (1<<15)) ProcSupport |= PROCSUPPORT_CMOV;
|
|
||||||
if(ExtendedFeatureFlags.d & (1<<23)) ProcSupport |= PROCSUPPORT_MMX;
|
|
||||||
}
|
|
||||||
if(ExtendedFeatureFlags.d & (1<<22)) ProcSupport |= PROCSUPPORT_AMD_MMXEXT;
|
|
||||||
if(ExtendedFeatureFlags.d & (1<<31)) ProcSupport |= PROCSUPPORT_AMD_3DNOW;
|
|
||||||
if(ExtendedFeatureFlags.d & (1<<30)) ProcSupport |= PROCSUPPORT_AMD_3DNOWEXT;
|
|
||||||
}
|
|
||||||
if(ExtendedVendorString.a >= 0x80000004u)
|
|
||||||
{
|
|
||||||
mpt::String::WriteAutoBuf(ProcBrandID) = cpuid(0x80000002u).as_string4() + cpuid(0x80000003u).as_string4() + cpuid(0x80000004u).as_string4();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We do not have to check if SSE got enabled by the OS because we only do
|
RealProcSupport = ProcSupport;
|
||||||
// support Windows >= XP. Windows will always enable SSE since Windows 98 SE.
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#elif MPT_COMPILER_MSVC && (defined(ENABLE_X86) || defined(ENABLE_X64))
|
||||||
|
|
||||||
|
|
||||||
|
void InitProcSupport()
|
||||||
|
{
|
||||||
|
|
||||||
|
RealProcSupport = 0;
|
||||||
|
ProcSupport = 0;
|
||||||
|
mpt::String::WriteAutoBuf(ProcVendorID) = "";
|
||||||
|
mpt::String::WriteAutoBuf(ProcBrandID) = "";
|
||||||
|
ProcFamily = 0;
|
||||||
|
ProcModel = 0;
|
||||||
|
ProcStepping = 0;
|
||||||
|
|
||||||
|
ProcSupport |= PROCSUPPORT_ASM_INTRIN;
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
if(IsProcessorFeaturePresent(PF_MMX_INSTRUCTIONS_AVAILABLE) != 0) ProcSupport |= PROCSUPPORT_MMX;
|
||||||
|
if(IsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE) != 0) ProcSupport |= PROCSUPPORT_SSE;
|
||||||
|
if(IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE) != 0) ProcSupport |= PROCSUPPORT_SSE2;
|
||||||
|
if(IsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE) != 0) ProcSupport |= PROCSUPPORT_SSE3;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
RealProcSupport = ProcSupport;
|
RealProcSupport = ProcSupport;
|
||||||
|
|
||||||
|
|
|
@ -16,26 +16,30 @@
|
||||||
OPENMPT_NAMESPACE_BEGIN
|
OPENMPT_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
|
||||||
#ifdef ENABLE_ASM
|
#ifdef MODPLUG_TRACKER
|
||||||
|
|
||||||
#define PROCSUPPORT_LM 0x00001 // Processor supports long mode (amd64)
|
#define PROCSUPPORT_ASM_INTRIN 0x00001 // assembly and intrinsics are enabled at runtime
|
||||||
#define PROCSUPPORT_CMOV 0x00004 // Processor supports conditional move instructions (i686)
|
#define PROCSUPPORT_CPUID 0x00002 // Processor supports modern cpuid
|
||||||
|
#define PROCSUPPORT_LM 0x00004 // Processor supports long mode (amd64)
|
||||||
#define PROCSUPPORT_MMX 0x00010 // Processor supports MMX instructions
|
#define PROCSUPPORT_MMX 0x00010 // Processor supports MMX instructions
|
||||||
#define PROCSUPPORT_AMD_MMXEXT 0x00020 // Processor supports AMD MMX extensions
|
|
||||||
#define PROCSUPPORT_AMD_3DNOW 0x00040 // Processor supports AMD 3DNow! instructions
|
|
||||||
#define PROCSUPPORT_AMD_3DNOWEXT 0x00080 // Processor supports AMD 3DNow!2 instructions
|
|
||||||
#define PROCSUPPORT_SSE 0x00100 // Processor supports SSE instructions
|
#define PROCSUPPORT_SSE 0x00100 // Processor supports SSE instructions
|
||||||
#define PROCSUPPORT_SSE2 0x00200 // Processor supports SSE2 instructions
|
#define PROCSUPPORT_SSE2 0x00200 // Processor supports SSE2 instructions
|
||||||
#define PROCSUPPORT_SSE3 0x00400 // Processor supports SSE3 instructions
|
#define PROCSUPPORT_SSE3 0x00400 // Processor supports SSE3 instructions
|
||||||
#define PROCSUPPORT_SSSE3 0x00800 // Processor supports SSSE3 instructions
|
#define PROCSUPPORT_SSSE3 0x00800 // Processor supports SSSE3 instructions
|
||||||
#define PROCSUPPORT_SSE4_1 0x01000 // Processor supports SSE4.1 instructions
|
#define PROCSUPPORT_SSE4_1 0x01000 // Processor supports SSE4.1 instructions
|
||||||
#define PROCSUPPORT_SSE4_2 0x02000 // Processor supports SSE4.2 instructions
|
#define PROCSUPPORT_SSE4_2 0x02000 // Processor supports SSE4.2 instructions
|
||||||
|
#define PROCSUPPORT_AVX 0x10000 // Processor supports AVX instructions
|
||||||
|
#define PROCSUPPORT_AVX2 0x20000 // Processor supports AVX2 instructions
|
||||||
|
|
||||||
static const uint32 PROCSUPPORT_i586 = 0u ;
|
static constexpr uint32 PROCSUPPORT_i586 = 0u ;
|
||||||
static const uint32 PROCSUPPORT_i686 = 0u | PROCSUPPORT_CMOV ;
|
static constexpr uint32 PROCSUPPORT_x86_SSE = 0u | PROCSUPPORT_SSE ;
|
||||||
static const uint32 PROCSUPPORT_x86_SSE = 0u | PROCSUPPORT_CMOV | PROCSUPPORT_SSE ;
|
static constexpr uint32 PROCSUPPORT_x86_SSE2 = 0u | PROCSUPPORT_SSE | PROCSUPPORT_SSE2 ;
|
||||||
static const uint32 PROCSUPPORT_x86_SSE2 = 0u | PROCSUPPORT_CMOV | PROCSUPPORT_SSE | PROCSUPPORT_SSE2 ;
|
static constexpr uint32 PROCSUPPORT_AMD64 = 0u | PROCSUPPORT_SSE | PROCSUPPORT_SSE2 | PROCSUPPORT_LM;
|
||||||
static const uint32 PROCSUPPORT_AMD64 = 0u | PROCSUPPORT_CMOV | PROCSUPPORT_SSE | PROCSUPPORT_SSE2 | PROCSUPPORT_LM;
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef ENABLE_ASM
|
||||||
|
|
||||||
extern uint32 RealProcSupport;
|
extern uint32 RealProcSupport;
|
||||||
extern uint32 ProcSupport;
|
extern uint32 ProcSupport;
|
||||||
|
|
|
@ -113,7 +113,7 @@ public:
|
||||||
|
|
||||||
inline void processByte(byte_type byte)
|
inline void processByte(byte_type byte)
|
||||||
{
|
{
|
||||||
MPT_CONSTANT_IF(reverseData)
|
if constexpr(reverseData)
|
||||||
{
|
{
|
||||||
value = (value >> 8) ^ read_table(static_cast<byte_type>((value & 0xff) ^ byte));
|
value = (value >> 8) ^ read_table(static_cast<byte_type>((value & 0xff) ^ byte));
|
||||||
} else
|
} else
|
||||||
|
@ -152,13 +152,11 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MPT_BYTE_IS_STD_BYTE
|
inline crc & process(std::byte c)
|
||||||
inline crc & process(mpt::byte c)
|
|
||||||
{
|
{
|
||||||
processByte(mpt::byte_cast<byte_type>(c));
|
processByte(mpt::byte_cast<byte_type>(c));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
template <typename InputIt>
|
template <typename InputIt>
|
||||||
crc & process(InputIt beg, InputIt end)
|
crc & process(InputIt beg, InputIt end)
|
||||||
|
@ -196,13 +194,11 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MPT_BYTE_IS_STD_BYTE
|
inline crc & operator () (std::byte c)
|
||||||
inline crc & operator () (mpt::byte c)
|
|
||||||
{
|
{
|
||||||
processByte(mpt::byte_cast<byte_type>(c));
|
processByte(mpt::byte_cast<byte_type>(c));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
template <typename InputIt>
|
template <typename InputIt>
|
||||||
crc & operator () (InputIt beg, InputIt end)
|
crc & operator () (InputIt beg, InputIt end)
|
||||||
|
|
|
@ -17,14 +17,14 @@
|
||||||
#include "mptBaseMacros.h"
|
#include "mptBaseMacros.h"
|
||||||
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#if !defined(_MFC_VER)
|
#if !defined(MPT_WITH_MFC)
|
||||||
#include <new>
|
#include <new>
|
||||||
#endif // !_MFC_VER
|
#endif // !MPT_WITH_MFC
|
||||||
|
|
||||||
#if defined(_MFC_VER)
|
#if defined(MPT_WITH_MFC)
|
||||||
// cppcheck-suppress missingInclude
|
// cppcheck-suppress missingInclude
|
||||||
#include <afx.h>
|
#include <afx.h>
|
||||||
#endif // _MFC_VER
|
#endif // MPT_WITH_MFC
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -35,21 +35,21 @@ OPENMPT_NAMESPACE_BEGIN
|
||||||
// Exception handling helpers, because MFC requires explicit deletion of the exception object,
|
// Exception handling helpers, because MFC requires explicit deletion of the exception object,
|
||||||
// Thus, always call exactly one of MPT_EXCEPTION_RETHROW_OUT_OF_MEMORY() or MPT_EXCEPTION_DELETE_OUT_OF_MEMORY(e).
|
// Thus, always call exactly one of MPT_EXCEPTION_RETHROW_OUT_OF_MEMORY() or MPT_EXCEPTION_DELETE_OUT_OF_MEMORY(e).
|
||||||
|
|
||||||
#if defined(_MFC_VER)
|
#if defined(MPT_WITH_MFC)
|
||||||
|
|
||||||
#define MPT_EXCEPTION_THROW_OUT_OF_MEMORY() MPT_DO { AfxThrowMemoryException(); } MPT_WHILE_0
|
#define MPT_EXCEPTION_THROW_OUT_OF_MEMORY() MPT_DO { AfxThrowMemoryException(); } MPT_WHILE_0
|
||||||
#define MPT_EXCEPTION_CATCH_OUT_OF_MEMORY(e) catch ( CMemoryException * e )
|
#define MPT_EXCEPTION_CATCH_OUT_OF_MEMORY(e) catch ( CMemoryException * e )
|
||||||
#define MPT_EXCEPTION_RETHROW_OUT_OF_MEMORY(e) MPT_DO { MPT_UNUSED_VARIABLE(e); throw; } MPT_WHILE_0
|
#define MPT_EXCEPTION_RETHROW_OUT_OF_MEMORY(e) MPT_DO { MPT_UNUSED_VARIABLE(e); throw; } MPT_WHILE_0
|
||||||
#define MPT_EXCEPTION_DELETE_OUT_OF_MEMORY(e) MPT_DO { if(e) { e->Delete(); e = nullptr; } } MPT_WHILE_0
|
#define MPT_EXCEPTION_DELETE_OUT_OF_MEMORY(e) MPT_DO { if(e) { e->Delete(); e = nullptr; } } MPT_WHILE_0
|
||||||
|
|
||||||
#else // !_MFC_VER
|
#else // !MPT_WITH_MFC
|
||||||
|
|
||||||
#define MPT_EXCEPTION_THROW_OUT_OF_MEMORY() MPT_DO { throw std::bad_alloc(); } MPT_WHILE_0
|
#define MPT_EXCEPTION_THROW_OUT_OF_MEMORY() MPT_DO { throw std::bad_alloc(); } MPT_WHILE_0
|
||||||
#define MPT_EXCEPTION_CATCH_OUT_OF_MEMORY(e) catch ( const std::bad_alloc & e )
|
#define MPT_EXCEPTION_CATCH_OUT_OF_MEMORY(e) catch ( const std::bad_alloc & e )
|
||||||
#define MPT_EXCEPTION_RETHROW_OUT_OF_MEMORY(e) MPT_DO { MPT_UNUSED_VARIABLE(e); throw; } MPT_WHILE_0
|
#define MPT_EXCEPTION_RETHROW_OUT_OF_MEMORY(e) MPT_DO { MPT_UNUSED_VARIABLE(e); throw; } MPT_WHILE_0
|
||||||
#define MPT_EXCEPTION_DELETE_OUT_OF_MEMORY(e) MPT_DO { MPT_UNUSED_VARIABLE(e); } MPT_WHILE_0
|
#define MPT_EXCEPTION_DELETE_OUT_OF_MEMORY(e) MPT_DO { MPT_UNUSED_VARIABLE(e); } MPT_WHILE_0
|
||||||
|
|
||||||
#endif // _MFC_VER
|
#endif // MPT_WITH_MFC
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -53,19 +53,19 @@ template <> inline std::string get_exception_text<std::string>(const std::except
|
||||||
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
||||||
template <> inline mpt::lstring get_exception_text<mpt::lstring>(const std::exception & e)
|
template <> inline mpt::lstring get_exception_text<mpt::lstring>(const std::exception & e)
|
||||||
{
|
{
|
||||||
return mpt::ToLocale(mpt::CharsetLocaleOrUTF8, mpt::get_exception_text_impl<std::string>(e));
|
return mpt::ToLocale(mpt::CharsetException, mpt::get_exception_text_impl<std::string>(e));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if MPT_WSTRING_FORMAT
|
#if MPT_WSTRING_FORMAT
|
||||||
template <> inline std::wstring get_exception_text<std::wstring>(const std::exception & e)
|
template <> inline std::wstring get_exception_text<std::wstring>(const std::exception & e)
|
||||||
{
|
{
|
||||||
return mpt::ToWide(mpt::CharsetLocaleOrUTF8, mpt::get_exception_text_impl<std::string>(e));
|
return mpt::ToWide(mpt::CharsetException, mpt::get_exception_text_impl<std::string>(e));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if MPT_USTRING_MODE_UTF8
|
#if MPT_USTRING_MODE_UTF8
|
||||||
template <> inline mpt::ustring get_exception_text<mpt::ustring>(const std::exception & e)
|
template <> inline mpt::ustring get_exception_text<mpt::ustring>(const std::exception & e)
|
||||||
{
|
{
|
||||||
return mpt::ToUnicode(mpt::CharsetLocaleOrUTF8, mpt::get_exception_text_impl<std::string>(e));
|
return mpt::ToUnicode(mpt::CharsetException, mpt::get_exception_text_impl<std::string>(e));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -99,12 +99,12 @@ mpt::tstring SafeOutputFile::convert_mode(std::ios_base::openmode mode, FlushMod
|
||||||
fopen_mode = _T("r");
|
fopen_mode = _T("r");
|
||||||
break;
|
break;
|
||||||
case std::ios_base::out:
|
case std::ios_base::out:
|
||||||
MPT_FALLTHROUGH;
|
[[fallthrough]];
|
||||||
case std::ios_base::out | std::ios_base::trunc:
|
case std::ios_base::out | std::ios_base::trunc:
|
||||||
fopen_mode = _T("w");
|
fopen_mode = _T("w");
|
||||||
break;
|
break;
|
||||||
case std::ios_base::app:
|
case std::ios_base::app:
|
||||||
MPT_FALLTHROUGH;
|
[[fallthrough]];
|
||||||
case std::ios_base::out | std::ios_base::app:
|
case std::ios_base::out | std::ios_base::app:
|
||||||
fopen_mode = _T("a");
|
fopen_mode = _T("a");
|
||||||
break;
|
break;
|
||||||
|
@ -115,7 +115,7 @@ mpt::tstring SafeOutputFile::convert_mode(std::ios_base::openmode mode, FlushMod
|
||||||
fopen_mode = _T("w+");
|
fopen_mode = _T("w+");
|
||||||
break;
|
break;
|
||||||
case std::ios_base::out | std::ios_base::in | std::ios_base::app:
|
case std::ios_base::out | std::ios_base::in | std::ios_base::app:
|
||||||
MPT_FALLTHROUGH;
|
[[fallthrough]];
|
||||||
case std::ios_base::in | std::ios_base::app:
|
case std::ios_base::in | std::ios_base::app:
|
||||||
fopen_mode = _T("a+");
|
fopen_mode = _T("a+");
|
||||||
break;
|
break;
|
||||||
|
@ -171,12 +171,25 @@ FILE * SafeOutputFile::internal_fopen(const mpt::PathString &filename, std::ios_
|
||||||
// cppcheck-suppress exceptThrowInDestructor
|
// cppcheck-suppress exceptThrowInDestructor
|
||||||
SafeOutputFile::~SafeOutputFile() noexcept(false)
|
SafeOutputFile::~SafeOutputFile() noexcept(false)
|
||||||
{
|
{
|
||||||
|
const bool mayThrow = (std::uncaught_exceptions() == 0);
|
||||||
if(!stream())
|
if(!stream())
|
||||||
{
|
{
|
||||||
|
#if MPT_COMPILER_MSVC
|
||||||
|
if(m_f)
|
||||||
|
{
|
||||||
|
fclose(m_f);
|
||||||
|
}
|
||||||
|
#endif // MPT_COMPILER_MSVC
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(!stream().rdbuf())
|
if(!stream().rdbuf())
|
||||||
{
|
{
|
||||||
|
#if MPT_COMPILER_MSVC
|
||||||
|
if(m_f)
|
||||||
|
{
|
||||||
|
fclose(m_f);
|
||||||
|
}
|
||||||
|
#endif // MPT_COMPILER_MSVC
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#if MPT_COMPILER_MSVC
|
#if MPT_COMPILER_MSVC
|
||||||
|
@ -210,8 +223,12 @@ SafeOutputFile::~SafeOutputFile() noexcept(false)
|
||||||
errorOnFlush = true;
|
errorOnFlush = true;
|
||||||
}
|
}
|
||||||
#endif // MPT_COMPILER_MSVC
|
#endif // MPT_COMPILER_MSVC
|
||||||
// ignore errorOnFlush here, and re-throw the earlier exception
|
if(mayThrow)
|
||||||
throw;
|
{
|
||||||
|
// ignore errorOnFlush here, and re-throw the earlier exception
|
||||||
|
// cppcheck-suppress exceptThrowInDestructor
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if MPT_COMPILER_MSVC
|
#if MPT_COMPILER_MSVC
|
||||||
|
@ -227,8 +244,9 @@ SafeOutputFile::~SafeOutputFile() noexcept(false)
|
||||||
errorOnFlush = true;
|
errorOnFlush = true;
|
||||||
}
|
}
|
||||||
#endif // MPT_COMPILER_MSVC
|
#endif // MPT_COMPILER_MSVC
|
||||||
if(errorOnFlush && (stream().exceptions() & (std::ios::badbit | std::ios::failbit)))
|
if(mayThrow && errorOnFlush && (stream().exceptions() & (std::ios::badbit | std::ios::failbit)))
|
||||||
{
|
{
|
||||||
|
// cppcheck-suppress exceptThrowInDestructor
|
||||||
throw std::ios_base::failure(std::string("Error flushing file buffers."));
|
throw std::ios_base::failure(std::string("Error flushing file buffers."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -243,11 +261,11 @@ SafeOutputFile::~SafeOutputFile() noexcept(false)
|
||||||
|
|
||||||
namespace mpt {
|
namespace mpt {
|
||||||
|
|
||||||
LazyFileRef & LazyFileRef::operator = (const std::vector<mpt::byte> &data)
|
LazyFileRef & LazyFileRef::operator = (const std::vector<std::byte> &data)
|
||||||
{
|
{
|
||||||
mpt::ofstream file(m_Filename, std::ios::binary);
|
mpt::ofstream file(m_Filename, std::ios::binary);
|
||||||
file.exceptions(std::ios_base::failbit | std::ios_base::badbit);
|
file.exceptions(std::ios_base::failbit | std::ios_base::badbit);
|
||||||
mpt::IO::WriteRaw(file, data.data(), data.size());
|
mpt::IO::WriteRaw(file, mpt::as_span(data));
|
||||||
mpt::IO::Flush(file);
|
mpt::IO::Flush(file);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -256,7 +274,7 @@ LazyFileRef & LazyFileRef::operator = (const std::vector<char> &data)
|
||||||
{
|
{
|
||||||
mpt::ofstream file(m_Filename, std::ios::binary);
|
mpt::ofstream file(m_Filename, std::ios::binary);
|
||||||
file.exceptions(std::ios_base::failbit | std::ios_base::badbit);
|
file.exceptions(std::ios_base::failbit | std::ios_base::badbit);
|
||||||
mpt::IO::WriteRaw(file, data.data(), data.size());
|
mpt::IO::WriteRaw(file, mpt::as_span(data));
|
||||||
mpt::IO::Flush(file);
|
mpt::IO::Flush(file);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -265,23 +283,23 @@ LazyFileRef & LazyFileRef::operator = (const std::string &data)
|
||||||
{
|
{
|
||||||
mpt::ofstream file(m_Filename, std::ios::binary);
|
mpt::ofstream file(m_Filename, std::ios::binary);
|
||||||
file.exceptions(std::ios_base::failbit | std::ios_base::badbit);
|
file.exceptions(std::ios_base::failbit | std::ios_base::badbit);
|
||||||
mpt::IO::WriteRaw(file, data.data(), data.size());
|
mpt::IO::WriteRaw(file, mpt::as_span(data));
|
||||||
mpt::IO::Flush(file);
|
mpt::IO::Flush(file);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
LazyFileRef::operator std::vector<mpt::byte> () const
|
LazyFileRef::operator std::vector<std::byte> () const
|
||||||
{
|
{
|
||||||
mpt::ifstream file(m_Filename, std::ios::binary);
|
mpt::ifstream file(m_Filename, std::ios::binary);
|
||||||
if(!mpt::IO::IsValid(file))
|
if(!mpt::IO::IsValid(file))
|
||||||
{
|
{
|
||||||
return std::vector<mpt::byte>();
|
return std::vector<std::byte>();
|
||||||
}
|
}
|
||||||
file.exceptions(std::ios_base::failbit | std::ios_base::badbit);
|
file.exceptions(std::ios_base::failbit | std::ios_base::badbit);
|
||||||
mpt::IO::SeekEnd(file);
|
mpt::IO::SeekEnd(file);
|
||||||
std::vector<mpt::byte> buf(mpt::saturate_cast<std::size_t>(mpt::IO::TellRead(file)));
|
std::vector<std::byte> buf(mpt::saturate_cast<std::size_t>(mpt::IO::TellRead(file)));
|
||||||
mpt::IO::SeekBegin(file);
|
mpt::IO::SeekBegin(file);
|
||||||
mpt::IO::ReadRaw(file, buf.data(), buf.size());
|
mpt::IO::ReadRaw(file, mpt::as_span(buf));
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,7 +314,7 @@ LazyFileRef::operator std::vector<char> () const
|
||||||
mpt::IO::SeekEnd(file);
|
mpt::IO::SeekEnd(file);
|
||||||
std::vector<char> buf(mpt::saturate_cast<std::size_t>(mpt::IO::TellRead(file)));
|
std::vector<char> buf(mpt::saturate_cast<std::size_t>(mpt::IO::TellRead(file)));
|
||||||
mpt::IO::SeekBegin(file);
|
mpt::IO::SeekBegin(file);
|
||||||
mpt::IO::ReadRaw(file, buf.data(), buf.size());
|
mpt::IO::ReadRaw(file, mpt::as_span(buf));
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,7 +329,7 @@ LazyFileRef::operator std::string () const
|
||||||
mpt::IO::SeekEnd(file);
|
mpt::IO::SeekEnd(file);
|
||||||
std::vector<char> buf(mpt::saturate_cast<std::size_t>(mpt::IO::TellRead(file)));
|
std::vector<char> buf(mpt::saturate_cast<std::size_t>(mpt::IO::TellRead(file)));
|
||||||
mpt::IO::SeekBegin(file);
|
mpt::IO::SeekBegin(file);
|
||||||
mpt::IO::ReadRaw(file, buf.data(), buf.size());
|
mpt::IO::ReadRaw(file, mpt::as_span(buf));
|
||||||
return std::string(buf.begin(), buf.end());
|
return std::string(buf.begin(), buf.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,149 +338,22 @@ LazyFileRef::operator std::string () const
|
||||||
#endif // MODPLUG_TRACKER
|
#endif // MODPLUG_TRACKER
|
||||||
|
|
||||||
|
|
||||||
|
bool InputFile::DefaultToLargeAddressSpaceUsage()
|
||||||
#ifdef MODPLUG_TRACKER
|
|
||||||
|
|
||||||
#if MPT_OS_WINDOWS
|
|
||||||
|
|
||||||
CMappedFile::~CMappedFile()
|
|
||||||
{
|
{
|
||||||
Close();
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool CMappedFile::Open(const mpt::PathString &filename)
|
|
||||||
{
|
|
||||||
m_hFile = CreateFile(
|
|
||||||
filename.AsNativePrefixed().c_str(),
|
|
||||||
GENERIC_READ,
|
|
||||||
FILE_SHARE_READ,
|
|
||||||
NULL,
|
|
||||||
OPEN_EXISTING,
|
|
||||||
FILE_ATTRIBUTE_NORMAL,
|
|
||||||
NULL);
|
|
||||||
if(m_hFile == INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
m_hFile = nullptr;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
m_FileName = filename;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void CMappedFile::Close()
|
|
||||||
{
|
|
||||||
m_FileName = mpt::PathString();
|
|
||||||
// Unlock file
|
|
||||||
if(m_hFMap)
|
|
||||||
{
|
|
||||||
if(m_pData)
|
|
||||||
{
|
|
||||||
UnmapViewOfFile(m_pData);
|
|
||||||
m_pData = nullptr;
|
|
||||||
}
|
|
||||||
CloseHandle(m_hFMap);
|
|
||||||
m_hFMap = nullptr;
|
|
||||||
} else if(m_pData)
|
|
||||||
{
|
|
||||||
free(m_pData);
|
|
||||||
m_pData = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close file handle
|
|
||||||
if(m_hFile)
|
|
||||||
{
|
|
||||||
CloseHandle(m_hFile);
|
|
||||||
m_hFile = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
size_t CMappedFile::GetLength()
|
|
||||||
{
|
|
||||||
LARGE_INTEGER size;
|
|
||||||
if(GetFileSizeEx(m_hFile, &size) == FALSE)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return mpt::saturate_cast<size_t>(size.QuadPart);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const mpt::byte *CMappedFile::Lock()
|
|
||||||
{
|
|
||||||
size_t length = GetLength();
|
|
||||||
if(!length) return nullptr;
|
|
||||||
|
|
||||||
void *lpStream;
|
|
||||||
|
|
||||||
HANDLE hmf = CreateFileMapping(
|
|
||||||
m_hFile,
|
|
||||||
NULL,
|
|
||||||
PAGE_READONLY,
|
|
||||||
0, 0,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
// Try memory-mapping first
|
|
||||||
if(hmf)
|
|
||||||
{
|
|
||||||
lpStream = MapViewOfFile(
|
|
||||||
hmf,
|
|
||||||
FILE_MAP_READ,
|
|
||||||
0, 0,
|
|
||||||
length);
|
|
||||||
if(lpStream)
|
|
||||||
{
|
|
||||||
m_hFMap = hmf;
|
|
||||||
m_pData = lpStream;
|
|
||||||
return mpt::void_cast<const mpt::byte*>(lpStream);
|
|
||||||
}
|
|
||||||
CloseHandle(hmf);
|
|
||||||
hmf = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback if memory-mapping fails for some weird reason
|
|
||||||
if((lpStream = malloc(length)) == nullptr) return nullptr;
|
|
||||||
memset(lpStream, 0, length);
|
|
||||||
size_t bytesToRead = length;
|
|
||||||
size_t bytesRead = 0;
|
|
||||||
while(bytesToRead > 0)
|
|
||||||
{
|
|
||||||
DWORD chunkToRead = mpt::saturate_cast<DWORD>(length);
|
|
||||||
DWORD chunkRead = 0;
|
|
||||||
if(ReadFile(m_hFile, mpt::void_cast<mpt::byte*>(lpStream) + bytesRead, chunkToRead, &chunkRead, NULL) == FALSE)
|
|
||||||
{
|
|
||||||
// error
|
|
||||||
free(lpStream);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
bytesRead += chunkRead;
|
|
||||||
bytesToRead -= chunkRead;
|
|
||||||
}
|
|
||||||
m_pData = lpStream;
|
|
||||||
return mpt::void_cast<const mpt::byte*>(lpStream);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // MPT_OS_WINDOWS
|
|
||||||
|
|
||||||
#endif // MODPLUG_TRACKER
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
InputFile::InputFile()
|
InputFile::InputFile()
|
||||||
|
: m_IsCached(false)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
InputFile::InputFile(const mpt::PathString &filename)
|
InputFile::InputFile(const mpt::PathString &filename, bool allowWholeFileCaching)
|
||||||
: m_Filename(filename)
|
: m_IsCached(false)
|
||||||
{
|
{
|
||||||
#if defined(MPT_FILEREADER_STD_ISTREAM)
|
Open(filename, allowWholeFileCaching);
|
||||||
m_File.open(m_Filename, std::ios::binary | std::ios::in);
|
|
||||||
#else
|
|
||||||
m_File.Open(m_Filename);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InputFile::~InputFile()
|
InputFile::~InputFile()
|
||||||
|
@ -471,57 +362,82 @@ InputFile::~InputFile()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool InputFile::Open(const mpt::PathString &filename)
|
bool InputFile::Open(const mpt::PathString &filename, bool allowWholeFileCaching)
|
||||||
{
|
{
|
||||||
|
m_IsCached = false;
|
||||||
|
m_Cache.resize(0);
|
||||||
|
m_Cache.shrink_to_fit();
|
||||||
m_Filename = filename;
|
m_Filename = filename;
|
||||||
#if defined(MPT_FILEREADER_STD_ISTREAM)
|
|
||||||
m_File.open(m_Filename, std::ios::binary | std::ios::in);
|
m_File.open(m_Filename, std::ios::binary | std::ios::in);
|
||||||
|
if(allowWholeFileCaching)
|
||||||
|
{
|
||||||
|
if(mpt::IO::IsReadSeekable(m_File))
|
||||||
|
{
|
||||||
|
if(!mpt::IO::SeekEnd(m_File))
|
||||||
|
{
|
||||||
|
m_File.close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
mpt::IO::Offset filesize = mpt::IO::TellRead(m_File);
|
||||||
|
if(!mpt::IO::SeekBegin(m_File))
|
||||||
|
{
|
||||||
|
m_File.close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(Util::TypeCanHoldValue<std::size_t>(filesize))
|
||||||
|
{
|
||||||
|
std::size_t buffersize = mpt::saturate_cast<std::size_t>(filesize);
|
||||||
|
m_Cache.resize(buffersize);
|
||||||
|
if(mpt::IO::ReadRaw(m_File, mpt::as_span(m_Cache)) != filesize)
|
||||||
|
{
|
||||||
|
m_File.close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(!mpt::IO::SeekBegin(m_File))
|
||||||
|
{
|
||||||
|
m_File.close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_IsCached = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return m_File.good();
|
return m_File.good();
|
||||||
#else
|
|
||||||
return m_File.Open(m_Filename);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool InputFile::IsValid() const
|
bool InputFile::IsValid() const
|
||||||
{
|
{
|
||||||
#if defined(MPT_FILEREADER_STD_ISTREAM)
|
|
||||||
return m_File.good();
|
return m_File.good();
|
||||||
#else
|
|
||||||
return m_File.IsOpen();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(MPT_FILEREADER_STD_ISTREAM)
|
|
||||||
|
|
||||||
InputFile::ContentsRef InputFile::Get()
|
bool InputFile::IsCached() const
|
||||||
{
|
{
|
||||||
InputFile::ContentsRef result;
|
return m_IsCached;
|
||||||
result.first = &m_File;
|
|
||||||
result.second = m_File.good() ? &m_Filename : nullptr;
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
InputFile::ContentsRef InputFile::Get()
|
const mpt::PathString& InputFile::GetFilenameRef() const
|
||||||
{
|
{
|
||||||
InputFile::ContentsRef result;
|
return m_Filename;
|
||||||
result.first.data = nullptr;
|
}
|
||||||
result.first.size = 0;
|
|
||||||
result.second = nullptr;
|
|
||||||
if(!m_File.IsOpen())
|
std::istream* InputFile::GetStream()
|
||||||
{
|
{
|
||||||
return result;
|
MPT_ASSERT(!m_IsCached);
|
||||||
}
|
return &m_File;
|
||||||
result.first.data = m_File.Lock();
|
}
|
||||||
if(result.first.data)
|
|
||||||
result.first.size = m_File.GetLength();
|
|
||||||
result.second = &m_Filename;
|
mpt::const_byte_span InputFile::GetCache()
|
||||||
return result;
|
{
|
||||||
|
MPT_ASSERT(m_IsCached);
|
||||||
|
return mpt::as_span(m_Cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#else // !MPT_ENABLE_FILEIO
|
#else // !MPT_ENABLE_FILEIO
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ template<typename Tbase>
|
||||||
inline void fstream_open(Tbase & base, const mpt::PathString & filename, std::ios_base::openmode mode)
|
inline void fstream_open(Tbase & base, const mpt::PathString & filename, std::ios_base::openmode mode)
|
||||||
{
|
{
|
||||||
#if defined(MPT_FSTREAM_DO_CONVERSIONS_ANSI)
|
#if defined(MPT_FSTREAM_DO_CONVERSIONS_ANSI)
|
||||||
base.open(mpt::ToCharset(mpt::CharsetLocale, filename.AsNative()).c_str(), mode);
|
base.open(mpt::ToCharset(mpt::Charset::Locale, filename.AsNative()).c_str(), mode);
|
||||||
#else
|
#else
|
||||||
base.open(filename.AsNativePrefixed().c_str(), mode);
|
base.open(filename.AsNativePrefixed().c_str(), mode);
|
||||||
#endif
|
#endif
|
||||||
|
@ -181,7 +181,7 @@ class SafeOutputFile
|
||||||
private:
|
private:
|
||||||
FlushMode m_FlushMode;
|
FlushMode m_FlushMode;
|
||||||
#if MPT_COMPILER_MSVC
|
#if MPT_COMPILER_MSVC
|
||||||
FILE *m_f;
|
FILE *m_f = nullptr;
|
||||||
#endif // MPT_COMPILER_MSVC
|
#endif // MPT_COMPILER_MSVC
|
||||||
mpt::ofstream m_s;
|
mpt::ofstream m_s;
|
||||||
#if MPT_COMPILER_MSVC
|
#if MPT_COMPILER_MSVC
|
||||||
|
@ -198,6 +198,8 @@ public:
|
||||||
, m_s(filename, mode)
|
, m_s(filename, mode)
|
||||||
#endif // MPT_COMPILER_MSVC
|
#endif // MPT_COMPILER_MSVC
|
||||||
{
|
{
|
||||||
|
if(!stream().is_open())
|
||||||
|
stream().setstate(mpt::ofstream::failbit);
|
||||||
}
|
}
|
||||||
mpt::ofstream& stream()
|
mpt::ofstream& stream()
|
||||||
{
|
{
|
||||||
|
@ -245,10 +247,10 @@ public:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
LazyFileRef & operator = (const std::vector<mpt::byte> &data);
|
LazyFileRef & operator = (const std::vector<std::byte> &data);
|
||||||
LazyFileRef & operator = (const std::vector<char> &data);
|
LazyFileRef & operator = (const std::vector<char> &data);
|
||||||
LazyFileRef & operator = (const std::string &data);
|
LazyFileRef & operator = (const std::string &data);
|
||||||
operator std::vector<mpt::byte> () const;
|
operator std::vector<std::byte> () const;
|
||||||
operator std::vector<char> () const;
|
operator std::vector<char> () const;
|
||||||
operator std::string () const;
|
operator std::string () const;
|
||||||
};
|
};
|
||||||
|
@ -259,59 +261,25 @@ public:
|
||||||
} // namespace mpt
|
} // namespace mpt
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef MODPLUG_TRACKER
|
|
||||||
#if MPT_OS_WINDOWS
|
|
||||||
class CMappedFile
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
HANDLE m_hFile;
|
|
||||||
HANDLE m_hFMap;
|
|
||||||
void *m_pData;
|
|
||||||
mpt::PathString m_FileName;
|
|
||||||
|
|
||||||
public:
|
|
||||||
CMappedFile() : m_hFile(nullptr), m_hFMap(nullptr), m_pData(nullptr) { }
|
|
||||||
~CMappedFile();
|
|
||||||
|
|
||||||
public:
|
|
||||||
bool Open(const mpt::PathString &filename);
|
|
||||||
bool IsOpen() const { return m_hFile != NULL && m_hFile != INVALID_HANDLE_VALUE; }
|
|
||||||
const mpt::PathString * GetpFilename() const { return &m_FileName; }
|
|
||||||
void Close();
|
|
||||||
size_t GetLength();
|
|
||||||
const mpt::byte *Lock();
|
|
||||||
};
|
|
||||||
#endif // MPT_OS_WINDOWS
|
|
||||||
#endif // MODPLUG_TRACKER
|
|
||||||
|
|
||||||
|
|
||||||
class InputFile
|
class InputFile
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
mpt::PathString m_Filename;
|
mpt::PathString m_Filename;
|
||||||
#ifdef MPT_FILEREADER_STD_ISTREAM
|
mpt::ifstream m_File;
|
||||||
mpt::ifstream m_File;
|
bool m_IsCached;
|
||||||
#else
|
std::vector<std::byte> m_Cache;
|
||||||
CMappedFile m_File;
|
public:
|
||||||
#endif
|
static bool DefaultToLargeAddressSpaceUsage();
|
||||||
public:
|
public:
|
||||||
InputFile();
|
InputFile();
|
||||||
InputFile(const mpt::PathString &filename);
|
InputFile(const mpt::PathString &filename, bool allowWholeFileCaching = DefaultToLargeAddressSpaceUsage());
|
||||||
~InputFile();
|
~InputFile();
|
||||||
bool Open(const mpt::PathString &filename);
|
bool Open(const mpt::PathString &filename, bool allowWholeFileCaching = DefaultToLargeAddressSpaceUsage());
|
||||||
bool IsValid() const;
|
bool IsValid() const;
|
||||||
#if defined(MPT_FILEREADER_STD_ISTREAM)
|
bool IsCached() const;
|
||||||
typedef std::pair<std::istream*, const mpt::PathString*> ContentsRef;
|
const mpt::PathString& GetFilenameRef() const;
|
||||||
#else
|
std::istream* GetStream();
|
||||||
struct Data
|
mpt::const_byte_span GetCache();
|
||||||
{
|
|
||||||
const mpt::byte *data;
|
|
||||||
std::size_t size;
|
|
||||||
};
|
|
||||||
typedef std::pair<InputFile::Data, const mpt::PathString*> ContentsRef;
|
|
||||||
#endif
|
|
||||||
InputFile::ContentsRef Get();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,9 +17,6 @@
|
||||||
#include <istream>
|
#include <istream>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#ifdef MPT_COMPILER_QUIRK_MSVC_STRINGSTREAM
|
|
||||||
#include <typeinfo>
|
|
||||||
#endif // MPT_COMPILER_QUIRK_MSVC_STRINGSTREAM
|
|
||||||
|
|
||||||
|
|
||||||
OPENMPT_NAMESPACE_BEGIN
|
OPENMPT_NAMESPACE_BEGIN
|
||||||
|
@ -30,100 +27,84 @@ namespace mpt {
|
||||||
namespace IO {
|
namespace IO {
|
||||||
|
|
||||||
|
|
||||||
#ifdef MPT_COMPILER_QUIRK_MSVC_STRINGSTREAM
|
//static_assert(sizeof(std::streamoff) == 8); // Assert 64bit file support.
|
||||||
|
|
||||||
// MSVC std::stringbuf (and thereby std::ostringstream, std::istringstream and
|
|
||||||
// std::stringstream) fail seekoff() when the stringbuf is currently empty.
|
|
||||||
// seekoff() can get called via tell*() or seek*() iostream members. tell*() has
|
|
||||||
// been special cased from VS2010 onwards to handle this specific case and
|
|
||||||
// changed to not fail when the stringbuf is empty.
|
|
||||||
// In addition to using out own wrapper around std::stringstream and
|
|
||||||
// std::stringbuf, we also work-around the plain native type's problem in case
|
|
||||||
// we get handed such an object from third party code. This mitigation of course
|
|
||||||
// requires using our consolidated and normalized IO functions.
|
|
||||||
// We use the following work-around strategy:
|
|
||||||
// * If the stream is already in failed state, we do not do any work-around
|
|
||||||
// and bail out early.
|
|
||||||
// * If the underlying streambuf is not a std::stringbuf, the work-around is
|
|
||||||
// not necessary and we skip it.
|
|
||||||
// * If querying the current position does not fail and returns a
|
|
||||||
// position > 0, the underlying stringbuf is not empty and we also bail out.
|
|
||||||
// * Otherwise, we actually query the string contained in the stringbuf to be
|
|
||||||
// empty. This operation is slow as it has to copy the string into a
|
|
||||||
// temporary.
|
|
||||||
// Note, however, that this is only ever necessary if the current position
|
|
||||||
// is 0. If it always has been 0, the stringbuf will be empty anyway and the
|
|
||||||
// copy does not cost anything measurable. If it got seeked to position 0,
|
|
||||||
// we have to pay the price. However, this should be relatively uncommmon in
|
|
||||||
// pratice.
|
|
||||||
// * The actual work-around consists of performing or emulating the requested
|
|
||||||
// operation and resetting the failed state afterwards.
|
|
||||||
|
|
||||||
static bool StreamIsStringStreamAndValidAndEmpty(std::ostream & f)
|
|
||||||
{
|
|
||||||
if(f.fail() || !f.rdbuf())
|
|
||||||
{ // failed
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(!dynamic_cast<std::stringbuf*>(f.rdbuf()) || (typeid(*(f.rdbuf())) != typeid(std::stringbuf)))
|
|
||||||
{ // no stringbuf
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
std::streampos pos = f.tellp();
|
|
||||||
f.clear(f.rdstate() & ~std::ios::failbit);
|
|
||||||
if(pos != std::streampos(-1) && pos > 0)
|
|
||||||
{ // if the position is not 0, the streambuf is not empty
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return dynamic_cast<std::stringbuf*>(f.rdbuf())->str().empty(); // slow
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool StreamIsStringStreamAndValidAndEmpty(std::istream & f)
|
|
||||||
{
|
|
||||||
if(f.fail() || !f.rdbuf())
|
|
||||||
{ // failed
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(!dynamic_cast<std::stringbuf*>(f.rdbuf()) || (typeid(*(f.rdbuf())) != typeid(std::stringbuf)))
|
|
||||||
{ // no stringbuf
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
std::streampos pos = f.tellg();
|
|
||||||
f.clear(f.rdstate() & ~std::ios::failbit);
|
|
||||||
if(pos != std::streampos(-1) && pos > 0)
|
|
||||||
{ // if the position is not 0, the streambuf is not empty
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return dynamic_cast<std::stringbuf*>(f.rdbuf())->str().empty(); // slow
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool StreamIsStringStreamAndValidAndEmpty(std::iostream & f)
|
|
||||||
{
|
|
||||||
if(f.fail() || !f.rdbuf())
|
|
||||||
{ // failed
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(!dynamic_cast<std::stringbuf*>(f.rdbuf()) || (typeid(*(f.rdbuf())) != typeid(std::stringbuf)))
|
|
||||||
{ // no stringbuf
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
std::streampos ipos = f.tellg();
|
|
||||||
f.clear(f.rdstate() & ~std::ios::failbit);
|
|
||||||
std::streampos opos = f.tellp();
|
|
||||||
f.clear(f.rdstate() & ~std::ios::failbit);
|
|
||||||
if((ipos != std::streampos(-1) && ipos > 0) || (opos != std::streampos(-1) && opos > 0))
|
|
||||||
{ // if the position is not 0, the streambuf is not empty
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return dynamic_cast<std::stringbuf*>(f.rdbuf())->str().empty(); // slow
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // MPT_COMPILER_QUIRK_MSVC_STRINGSTREAM
|
|
||||||
|
|
||||||
//STATIC_ASSERT(sizeof(std::streamoff) == 8); // Assert 64bit file support.
|
|
||||||
bool IsValid(std::ostream & f) { return !f.fail(); }
|
bool IsValid(std::ostream & f) { return !f.fail(); }
|
||||||
bool IsValid(std::istream & f) { return !f.fail(); }
|
bool IsValid(std::istream & f) { return !f.fail(); }
|
||||||
bool IsValid(std::iostream & f) { return !f.fail(); }
|
bool IsValid(std::iostream & f) { return !f.fail(); }
|
||||||
|
bool IsReadSeekable(std::istream & f)
|
||||||
|
{
|
||||||
|
f.clear();
|
||||||
|
std::streampos oldpos = f.tellg();
|
||||||
|
if(f.fail() || oldpos == std::streampos(-1))
|
||||||
|
{
|
||||||
|
f.clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
f.seekg(0, std::ios::beg);
|
||||||
|
if(f.fail())
|
||||||
|
{
|
||||||
|
f.clear();
|
||||||
|
f.seekg(oldpos);
|
||||||
|
f.clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
f.seekg(0, std::ios::end);
|
||||||
|
if(f.fail())
|
||||||
|
{
|
||||||
|
f.clear();
|
||||||
|
f.seekg(oldpos);
|
||||||
|
f.clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::streampos length = f.tellg();
|
||||||
|
if(f.fail() || length == std::streampos(-1))
|
||||||
|
{
|
||||||
|
f.clear();
|
||||||
|
f.seekg(oldpos);
|
||||||
|
f.clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
f.seekg(oldpos);
|
||||||
|
f.clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool IsWriteSeekable(std::ostream & f)
|
||||||
|
{
|
||||||
|
f.clear();
|
||||||
|
std::streampos oldpos = f.tellp();
|
||||||
|
if(f.fail() || oldpos == std::streampos(-1))
|
||||||
|
{
|
||||||
|
f.clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
f.seekp(0, std::ios::beg);
|
||||||
|
if(f.fail())
|
||||||
|
{
|
||||||
|
f.clear();
|
||||||
|
f.seekp(oldpos);
|
||||||
|
f.clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
f.seekp(0, std::ios::end);
|
||||||
|
if(f.fail())
|
||||||
|
{
|
||||||
|
f.clear();
|
||||||
|
f.seekp(oldpos);
|
||||||
|
f.clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::streampos length = f.tellp();
|
||||||
|
if(f.fail() || length == std::streampos(-1))
|
||||||
|
{
|
||||||
|
f.clear();
|
||||||
|
f.seekp(oldpos);
|
||||||
|
f.clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
f.seekp(oldpos);
|
||||||
|
f.clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
IO::Offset TellRead(std::istream & f)
|
IO::Offset TellRead(std::istream & f)
|
||||||
{
|
{
|
||||||
return f.tellg();
|
return f.tellg();
|
||||||
|
@ -134,150 +115,60 @@ IO::Offset TellWrite(std::ostream & f)
|
||||||
}
|
}
|
||||||
bool SeekBegin(std::ostream & f)
|
bool SeekBegin(std::ostream & f)
|
||||||
{
|
{
|
||||||
#ifdef MPT_COMPILER_QUIRK_MSVC_STRINGSTREAM
|
|
||||||
if(StreamIsStringStreamAndValidAndEmpty(f))
|
|
||||||
{ // VS std::stringbuf fail seek when the internal buffer is empty. Work-around it in case the stream is not already in failed state.
|
|
||||||
f.seekp(0); f.clear(f.rdstate() & ~std::ios::failbit); return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
f.seekp(0); return !f.fail();
|
f.seekp(0); return !f.fail();
|
||||||
}
|
}
|
||||||
bool SeekBegin(std::istream & f)
|
bool SeekBegin(std::istream & f)
|
||||||
{
|
{
|
||||||
#ifdef MPT_COMPILER_QUIRK_MSVC_STRINGSTREAM
|
|
||||||
if(StreamIsStringStreamAndValidAndEmpty(f))
|
|
||||||
{
|
|
||||||
f.seekg(0); f.clear(f.rdstate() & ~std::ios::failbit); return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
f.seekg(0); return !f.fail();
|
f.seekg(0); return !f.fail();
|
||||||
}
|
}
|
||||||
bool SeekBegin(std::iostream & f)
|
bool SeekBegin(std::iostream & f)
|
||||||
{
|
{
|
||||||
#ifdef MPT_COMPILER_QUIRK_MSVC_STRINGSTREAM
|
|
||||||
if(StreamIsStringStreamAndValidAndEmpty(f))
|
|
||||||
{
|
|
||||||
f.seekg(0); f.clear(f.rdstate() & ~std::ios::failbit); f.seekp(0); f.clear(f.rdstate() & ~std::ios::failbit); return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
f.seekg(0); f.seekp(0); return !f.fail();
|
f.seekg(0); f.seekp(0); return !f.fail();
|
||||||
}
|
}
|
||||||
bool SeekEnd(std::ostream & f)
|
bool SeekEnd(std::ostream & f)
|
||||||
{
|
{
|
||||||
#ifdef MPT_COMPILER_QUIRK_MSVC_STRINGSTREAM
|
|
||||||
if(StreamIsStringStreamAndValidAndEmpty(f))
|
|
||||||
{
|
|
||||||
f.seekp(0); f.clear(f.rdstate() & ~std::ios::failbit); return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
f.seekp(0, std::ios::end); return !f.fail();
|
f.seekp(0, std::ios::end); return !f.fail();
|
||||||
}
|
}
|
||||||
bool SeekEnd(std::istream & f)
|
bool SeekEnd(std::istream & f)
|
||||||
{
|
{
|
||||||
#ifdef MPT_COMPILER_QUIRK_MSVC_STRINGSTREAM
|
|
||||||
if(StreamIsStringStreamAndValidAndEmpty(f))
|
|
||||||
{
|
|
||||||
f.seekg(0); f.clear(f.rdstate() & ~std::ios::failbit); return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
f.seekg(0, std::ios::end); return !f.fail();
|
f.seekg(0, std::ios::end); return !f.fail();
|
||||||
}
|
}
|
||||||
bool SeekEnd(std::iostream & f)
|
bool SeekEnd(std::iostream & f)
|
||||||
{
|
{
|
||||||
#ifdef MPT_COMPILER_QUIRK_MSVC_STRINGSTREAM
|
|
||||||
if(StreamIsStringStreamAndValidAndEmpty(f))
|
|
||||||
{
|
|
||||||
f.seekg(0); f.clear(f.rdstate() & ~std::ios::failbit); f.seekp(0); f.clear(f.rdstate() & ~std::ios::failbit); return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
f.seekg(0, std::ios::end); f.seekp(0, std::ios::end); return !f.fail();
|
f.seekg(0, std::ios::end); f.seekp(0, std::ios::end); return !f.fail();
|
||||||
}
|
}
|
||||||
bool SeekAbsolute(std::ostream & f, IO::Offset pos)
|
bool SeekAbsolute(std::ostream & f, IO::Offset pos)
|
||||||
{
|
{
|
||||||
if(!OffsetFits<std::streamoff>(pos)) { return false; }
|
if(!OffsetFits<std::streamoff>(pos)) { return false; }
|
||||||
#ifdef MPT_COMPILER_QUIRK_MSVC_STRINGSTREAM
|
|
||||||
if(StreamIsStringStreamAndValidAndEmpty(f))
|
|
||||||
{
|
|
||||||
if(pos == 0)
|
|
||||||
{
|
|
||||||
f.seekp(static_cast<std::streamoff>(pos), std::ios::beg); f.clear(f.rdstate() & ~std::ios::failbit); return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
f.seekp(static_cast<std::streamoff>(pos), std::ios::beg); return !f.fail();
|
f.seekp(static_cast<std::streamoff>(pos), std::ios::beg); return !f.fail();
|
||||||
}
|
}
|
||||||
bool SeekAbsolute(std::istream & f, IO::Offset pos)
|
bool SeekAbsolute(std::istream & f, IO::Offset pos)
|
||||||
{
|
{
|
||||||
if(!OffsetFits<std::streamoff>(pos)) { return false; }
|
if(!OffsetFits<std::streamoff>(pos)) { return false; }
|
||||||
#ifdef MPT_COMPILER_QUIRK_MSVC_STRINGSTREAM
|
|
||||||
if(StreamIsStringStreamAndValidAndEmpty(f))
|
|
||||||
{
|
|
||||||
if(pos == 0)
|
|
||||||
{
|
|
||||||
f.seekg(static_cast<std::streamoff>(pos), std::ios::beg); f.clear(f.rdstate() & ~std::ios::failbit); return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
f.seekg(static_cast<std::streamoff>(pos), std::ios::beg); return !f.fail();
|
f.seekg(static_cast<std::streamoff>(pos), std::ios::beg); return !f.fail();
|
||||||
}
|
}
|
||||||
bool SeekAbsolute(std::iostream & f, IO::Offset pos)
|
bool SeekAbsolute(std::iostream & f, IO::Offset pos)
|
||||||
{
|
{
|
||||||
if(!OffsetFits<std::streamoff>(pos)) { return false; }
|
if(!OffsetFits<std::streamoff>(pos)) { return false; }
|
||||||
#ifdef MPT_COMPILER_QUIRK_MSVC_STRINGSTREAM
|
|
||||||
if(StreamIsStringStreamAndValidAndEmpty(f))
|
|
||||||
{
|
|
||||||
if(pos == 0)
|
|
||||||
{
|
|
||||||
f.seekg(static_cast<std::streamoff>(pos), std::ios::beg); f.clear(f.rdstate() & ~std::ios::failbit); f.seekp(static_cast<std::streamoff>(pos), std::ios::beg); f.clear(f.rdstate() & ~std::ios::failbit); return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
f.seekg(static_cast<std::streamoff>(pos), std::ios::beg); f.seekp(static_cast<std::streamoff>(pos), std::ios::beg); return !f.fail();
|
f.seekg(static_cast<std::streamoff>(pos), std::ios::beg); f.seekp(static_cast<std::streamoff>(pos), std::ios::beg); return !f.fail();
|
||||||
}
|
}
|
||||||
bool SeekRelative(std::ostream & f, IO::Offset off)
|
bool SeekRelative(std::ostream & f, IO::Offset off)
|
||||||
{
|
{
|
||||||
if(!OffsetFits<std::streamoff>(off)) { return false; }
|
if(!OffsetFits<std::streamoff>(off)) { return false; }
|
||||||
#ifdef MPT_COMPILER_QUIRK_MSVC_STRINGSTREAM
|
|
||||||
if(StreamIsStringStreamAndValidAndEmpty(f))
|
|
||||||
{
|
|
||||||
if(off == 0)
|
|
||||||
{
|
|
||||||
f.seekp(static_cast<std::streamoff>(off), std::ios::cur); f.clear(f.rdstate() & ~std::ios::failbit); return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
f.seekp(static_cast<std::streamoff>(off), std::ios::cur); return !f.fail();
|
f.seekp(static_cast<std::streamoff>(off), std::ios::cur); return !f.fail();
|
||||||
}
|
}
|
||||||
bool SeekRelative(std::istream & f, IO::Offset off)
|
bool SeekRelative(std::istream & f, IO::Offset off)
|
||||||
{
|
{
|
||||||
if(!OffsetFits<std::streamoff>(off)) { return false; }
|
if(!OffsetFits<std::streamoff>(off)) { return false; }
|
||||||
#ifdef MPT_COMPILER_QUIRK_MSVC_STRINGSTREAM
|
|
||||||
if(StreamIsStringStreamAndValidAndEmpty(f))
|
|
||||||
{
|
|
||||||
if(off == 0)
|
|
||||||
{
|
|
||||||
f.seekg(static_cast<std::streamoff>(off), std::ios::cur); f.clear(f.rdstate() & ~std::ios::failbit); return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
f.seekg(static_cast<std::streamoff>(off), std::ios::cur); return !f.fail();
|
f.seekg(static_cast<std::streamoff>(off), std::ios::cur); return !f.fail();
|
||||||
}
|
}
|
||||||
bool SeekRelative(std::iostream & f, IO::Offset off)
|
bool SeekRelative(std::iostream & f, IO::Offset off)
|
||||||
{
|
{
|
||||||
if(!OffsetFits<std::streamoff>(off)) { return false; }
|
if(!OffsetFits<std::streamoff>(off)) { return false; }
|
||||||
#ifdef MPT_COMPILER_QUIRK_MSVC_STRINGSTREAM
|
|
||||||
if(StreamIsStringStreamAndValidAndEmpty(f))
|
|
||||||
{
|
|
||||||
if(off == 0)
|
|
||||||
{
|
|
||||||
f.seekg(static_cast<std::streamoff>(off), std::ios::cur); f.clear(f.rdstate() & ~std::ios::failbit); f.seekp(static_cast<std::streamoff>(off), std::ios::cur); f.clear(f.rdstate() & ~std::ios::failbit); return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
f.seekg(static_cast<std::streamoff>(off), std::ios::cur); f.seekp(static_cast<std::streamoff>(off), std::ios::cur); return !f.fail();
|
f.seekg(static_cast<std::streamoff>(off), std::ios::cur); f.seekp(static_cast<std::streamoff>(off), std::ios::cur); return !f.fail();
|
||||||
}
|
}
|
||||||
IO::Offset ReadRawImpl(std::istream & f, mpt::byte * data, std::size_t size) { return f.read(mpt::byte_cast<char *>(data), size) ? f.gcount() : std::streamsize(0); }
|
IO::Offset ReadRawImpl(std::istream & f, mpt::byte_span data) { f.read(mpt::byte_cast<char *>(data.data()), data.size()); return f.gcount(); }
|
||||||
bool WriteRawImpl(std::ostream & f, const mpt::byte * data, std::size_t size) { f.write(mpt::byte_cast<const char *>(data), size); return !f.fail(); }
|
bool WriteRawImpl(std::ostream & f, mpt::const_byte_span data) { f.write(mpt::byte_cast<const char *>(data.data()), data.size()); return !f.fail(); }
|
||||||
bool IsEof(std::istream & f) { return f.eof(); }
|
bool IsEof(std::istream & f) { return f.eof(); }
|
||||||
bool Flush(std::ostream & f) { f.flush(); return !f.fail(); }
|
bool Flush(std::ostream & f) { f.flush(); return !f.fail(); }
|
||||||
|
|
||||||
|
@ -289,15 +180,19 @@ bool Flush(std::ostream & f) { f.flush(); return !f.fail(); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(MPT_FILEREADER_STD_ISTREAM)
|
FileDataContainerSeekable::FileDataContainerSeekable(off_t streamLength, bool buffered)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
FileDataContainerSeekable::FileDataContainerSeekable(off_t streamLength)
|
|
||||||
: streamLength(streamLength)
|
: streamLength(streamLength)
|
||||||
, cached(false)
|
, cached(false)
|
||||||
|
, m_Buffered(buffered)
|
||||||
|
, m_Buffer(m_Buffered ? static_cast<off_t>(BUFFER_SIZE) : 0)
|
||||||
{
|
{
|
||||||
return;
|
if(m_Buffered)
|
||||||
|
{
|
||||||
|
for(std::size_t chunkIndex = 0; chunkIndex < NUM_CHUNKS; ++chunkIndex)
|
||||||
|
{
|
||||||
|
m_ChunkIndexLRU[chunkIndex] = chunkIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileDataContainerSeekable::CacheStream() const
|
void FileDataContainerSeekable::CacheStream() const
|
||||||
|
@ -306,11 +201,48 @@ void FileDataContainerSeekable::CacheStream() const
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if(m_Buffered)
|
||||||
|
{
|
||||||
|
m_Buffered = false;
|
||||||
|
for (std::size_t chunkIndex = 0; chunkIndex < NUM_CHUNKS; ++chunkIndex)
|
||||||
|
{
|
||||||
|
m_ChunkInfo[chunkIndex].ChunkValid = false;
|
||||||
|
}
|
||||||
|
m_Buffer.resize(0);
|
||||||
|
m_Buffer.shrink_to_fit();
|
||||||
|
}
|
||||||
cache.resize(streamLength);
|
cache.resize(streamLength);
|
||||||
InternalRead(cache.data(), 0, streamLength);
|
InternalRead(cache.data(), 0, streamLength);
|
||||||
cached = true;
|
cached = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::size_t FileDataContainerSeekable::InternalFillPageAndReturnIndex(off_t pos) const
|
||||||
|
{
|
||||||
|
pos = Util::AlignDown(pos, static_cast<off_t>(CHUNK_SIZE));
|
||||||
|
for(std::size_t chunkLRUIndex = 0; chunkLRUIndex < NUM_CHUNKS; ++chunkLRUIndex)
|
||||||
|
{
|
||||||
|
std::size_t chunkIndex = m_ChunkIndexLRU[chunkLRUIndex];
|
||||||
|
if(m_ChunkInfo[chunkIndex].ChunkValid && (m_ChunkInfo[chunkIndex].ChunkOffset == pos))
|
||||||
|
{
|
||||||
|
std::size_t chunk = std::move(m_ChunkIndexLRU[chunkLRUIndex]);
|
||||||
|
std::move_backward(m_ChunkIndexLRU.begin(), m_ChunkIndexLRU.begin() + chunkLRUIndex, m_ChunkIndexLRU.begin() + (chunkLRUIndex + 1));
|
||||||
|
m_ChunkIndexLRU[0] = std::move(chunk);
|
||||||
|
return chunkIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::size_t chunk = std::move(m_ChunkIndexLRU[NUM_CHUNKS - 1]);
|
||||||
|
std::move_backward(m_ChunkIndexLRU.begin(), m_ChunkIndexLRU.begin() + (NUM_CHUNKS - 1), m_ChunkIndexLRU.begin() + NUM_CHUNKS);
|
||||||
|
m_ChunkIndexLRU[0] = std::move(chunk);
|
||||||
|
}
|
||||||
|
std::size_t chunkIndex = m_ChunkIndexLRU[0];
|
||||||
|
chunk_info& chunk = m_ChunkInfo[chunkIndex];
|
||||||
|
chunk.ChunkOffset = pos;
|
||||||
|
chunk.ChunkLength = InternalRead(chunk_data(chunkIndex).data(), pos, CHUNK_SIZE);
|
||||||
|
chunk.ChunkValid = true;
|
||||||
|
return chunkIndex;
|
||||||
|
}
|
||||||
|
|
||||||
bool FileDataContainerSeekable::IsValid() const
|
bool FileDataContainerSeekable::IsValid() const
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
@ -326,7 +258,7 @@ bool FileDataContainerSeekable::HasPinnedView() const
|
||||||
return cached;
|
return cached;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mpt::byte *FileDataContainerSeekable::GetRawData() const
|
const std::byte *FileDataContainerSeekable::GetRawData() const
|
||||||
{
|
{
|
||||||
CacheStream();
|
CacheStream();
|
||||||
return cache.data();
|
return cache.data();
|
||||||
|
@ -337,57 +269,51 @@ IFileDataContainer::off_t FileDataContainerSeekable::GetLength() const
|
||||||
return streamLength;
|
return streamLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
IFileDataContainer::off_t FileDataContainerSeekable::Read(mpt::byte *dst, IFileDataContainer::off_t pos, IFileDataContainer::off_t count) const
|
IFileDataContainer::off_t FileDataContainerSeekable::Read(std::byte *dst, IFileDataContainer::off_t pos, IFileDataContainer::off_t count) const
|
||||||
{
|
{
|
||||||
if(cached)
|
if(cached)
|
||||||
{
|
{
|
||||||
IFileDataContainer::off_t cache_avail = std::min<IFileDataContainer::off_t>(IFileDataContainer::off_t(cache.size()) - pos, count);
|
IFileDataContainer::off_t cache_avail = std::min(IFileDataContainer::off_t(cache.size()) - pos, count);
|
||||||
std::copy(cache.begin() + pos, cache.begin() + pos + cache_avail, dst);
|
std::copy(cache.begin() + pos, cache.begin() + pos + cache_avail, dst);
|
||||||
return cache_avail;
|
return cache_avail;
|
||||||
} else
|
} else
|
||||||
|
{
|
||||||
|
return InternalReadBuffered(dst, pos, count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IFileDataContainer::off_t FileDataContainerSeekable::InternalReadBuffered(std::byte* dst, off_t pos, off_t count) const
|
||||||
|
{
|
||||||
|
if(!m_Buffered)
|
||||||
{
|
{
|
||||||
return InternalRead(dst, pos, count);
|
return InternalRead(dst, pos, count);
|
||||||
}
|
}
|
||||||
|
off_t totalRead = 0;
|
||||||
|
while (count > 0)
|
||||||
|
{
|
||||||
|
std::size_t chunkIndex = InternalFillPageAndReturnIndex(pos);
|
||||||
|
off_t pageSkip = pos - m_ChunkInfo[chunkIndex].ChunkOffset;
|
||||||
|
off_t chunkWanted = std::min(static_cast<off_t>(CHUNK_SIZE) - pageSkip, count);
|
||||||
|
off_t chunkGot = (m_ChunkInfo[chunkIndex].ChunkLength > pageSkip) ? (m_ChunkInfo[chunkIndex].ChunkLength - pageSkip) : 0;
|
||||||
|
off_t chunk = std::min(chunkWanted, chunkGot);
|
||||||
|
std::copy(chunk_data(chunkIndex).data() + pageSkip, chunk_data(chunkIndex).data() + pageSkip + chunk, dst);
|
||||||
|
pos += chunk;
|
||||||
|
dst += chunk;
|
||||||
|
totalRead += chunk;
|
||||||
|
count -= chunk;
|
||||||
|
if (chunkWanted > chunk)
|
||||||
|
{
|
||||||
|
return totalRead;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return totalRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool FileDataContainerStdStreamSeekable::IsSeekable(std::istream *stream)
|
bool FileDataContainerStdStreamSeekable::IsSeekable(std::istream *stream)
|
||||||
{
|
{
|
||||||
stream->clear();
|
return mpt::IO::IsReadSeekable(*stream);
|
||||||
std::streampos oldpos = stream->tellg();
|
|
||||||
if(stream->fail() || oldpos == std::streampos(-1))
|
|
||||||
{
|
|
||||||
stream->clear();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
stream->seekg(0, std::ios::beg);
|
|
||||||
if(stream->fail())
|
|
||||||
{
|
|
||||||
stream->clear();
|
|
||||||
stream->seekg(oldpos);
|
|
||||||
stream->clear();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
stream->seekg(0, std::ios::end);
|
|
||||||
if(stream->fail())
|
|
||||||
{
|
|
||||||
stream->clear();
|
|
||||||
stream->seekg(oldpos);
|
|
||||||
stream->clear();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
std::streampos length = stream->tellg();
|
|
||||||
if(stream->fail() || length == std::streampos(-1))
|
|
||||||
{
|
|
||||||
stream->clear();
|
|
||||||
stream->seekg(oldpos);
|
|
||||||
stream->clear();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
stream->seekg(oldpos);
|
|
||||||
stream->clear();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IFileDataContainer::off_t FileDataContainerStdStreamSeekable::GetLength(std::istream *stream)
|
IFileDataContainer::off_t FileDataContainerStdStreamSeekable::GetLength(std::istream *stream)
|
||||||
|
@ -401,13 +327,13 @@ IFileDataContainer::off_t FileDataContainerStdStreamSeekable::GetLength(std::ist
|
||||||
}
|
}
|
||||||
|
|
||||||
FileDataContainerStdStreamSeekable::FileDataContainerStdStreamSeekable(std::istream *s)
|
FileDataContainerStdStreamSeekable::FileDataContainerStdStreamSeekable(std::istream *s)
|
||||||
: FileDataContainerSeekable(GetLength(s))
|
: FileDataContainerSeekable(GetLength(s), true)
|
||||||
, stream(s)
|
, stream(s)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
IFileDataContainer::off_t FileDataContainerStdStreamSeekable::InternalRead(mpt::byte *dst, off_t pos, off_t count) const
|
IFileDataContainer::off_t FileDataContainerStdStreamSeekable::InternalRead(std::byte *dst, off_t pos, off_t count) const
|
||||||
{
|
{
|
||||||
stream->clear(); // tellg needs eof and fail bits unset
|
stream->clear(); // tellg needs eof and fail bits unset
|
||||||
std::streampos currentpos = stream->tellg();
|
std::streampos currentpos = stream->tellg();
|
||||||
|
@ -487,7 +413,7 @@ void FileDataContainerUnseekable::CacheStreamUpTo(off_t pos, off_t length) const
|
||||||
streamFullyCached = true;
|
streamFullyCached = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileDataContainerUnseekable::ReadCached(mpt::byte *dst, IFileDataContainer::off_t pos, IFileDataContainer::off_t count) const
|
void FileDataContainerUnseekable::ReadCached(std::byte *dst, IFileDataContainer::off_t pos, IFileDataContainer::off_t count) const
|
||||||
{
|
{
|
||||||
std::copy(cache.begin() + pos, cache.begin() + pos + count, dst);
|
std::copy(cache.begin() + pos, cache.begin() + pos + count, dst);
|
||||||
}
|
}
|
||||||
|
@ -507,7 +433,7 @@ bool FileDataContainerUnseekable::HasPinnedView() const
|
||||||
return true; // we have the cache which is required for seeking anyway
|
return true; // we have the cache which is required for seeking anyway
|
||||||
}
|
}
|
||||||
|
|
||||||
const mpt::byte *FileDataContainerUnseekable::GetRawData() const
|
const std::byte *FileDataContainerUnseekable::GetRawData() const
|
||||||
{
|
{
|
||||||
CacheStream();
|
CacheStream();
|
||||||
return cache.data();
|
return cache.data();
|
||||||
|
@ -519,14 +445,14 @@ IFileDataContainer::off_t FileDataContainerUnseekable::GetLength() const
|
||||||
return cachesize;
|
return cachesize;
|
||||||
}
|
}
|
||||||
|
|
||||||
IFileDataContainer::off_t FileDataContainerUnseekable::Read(mpt::byte *dst, IFileDataContainer::off_t pos, IFileDataContainer::off_t count) const
|
IFileDataContainer::off_t FileDataContainerUnseekable::Read(std::byte *dst, IFileDataContainer::off_t pos, IFileDataContainer::off_t count) const
|
||||||
{
|
{
|
||||||
CacheStreamUpTo(pos, count);
|
CacheStreamUpTo(pos, count);
|
||||||
if(pos >= IFileDataContainer::off_t(cachesize))
|
if(pos >= IFileDataContainer::off_t(cachesize))
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
IFileDataContainer::off_t cache_avail = std::min<IFileDataContainer::off_t>(IFileDataContainer::off_t(cachesize) - pos, count);
|
IFileDataContainer::off_t cache_avail = std::min(IFileDataContainer::off_t(cachesize) - pos, count);
|
||||||
ReadCached(dst, pos, cache_avail);
|
ReadCached(dst, pos, cache_avail);
|
||||||
return cache_avail;
|
return cache_avail;
|
||||||
}
|
}
|
||||||
|
@ -552,7 +478,7 @@ IFileDataContainer::off_t FileDataContainerUnseekable::GetReadableLength(IFileDa
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return std::min<IFileDataContainer::off_t>(cachesize - pos, length);
|
return std::min(static_cast<IFileDataContainer::off_t>(cachesize) - pos, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -574,7 +500,7 @@ bool FileDataContainerStdStream::InternalEof() const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IFileDataContainer::off_t FileDataContainerStdStream::InternalRead(mpt::byte *dst, off_t count) const
|
IFileDataContainer::off_t FileDataContainerStdStream::InternalRead(std::byte *dst, off_t count) const
|
||||||
{
|
{
|
||||||
stream->read(mpt::byte_cast<char*>(dst), count);
|
stream->read(mpt::byte_cast<char*>(dst), count);
|
||||||
return static_cast<std::size_t>(stream->gcount());
|
return static_cast<std::size_t>(stream->gcount());
|
||||||
|
@ -664,13 +590,13 @@ IFileDataContainer::off_t FileDataContainerCallbackStreamSeekable::GetLength(Cal
|
||||||
}
|
}
|
||||||
|
|
||||||
FileDataContainerCallbackStreamSeekable::FileDataContainerCallbackStreamSeekable(CallbackStream s)
|
FileDataContainerCallbackStreamSeekable::FileDataContainerCallbackStreamSeekable(CallbackStream s)
|
||||||
: FileDataContainerSeekable(GetLength(s))
|
: FileDataContainerSeekable(GetLength(s), false)
|
||||||
, stream(s)
|
, stream(s)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
IFileDataContainer::off_t FileDataContainerCallbackStreamSeekable::InternalRead(mpt::byte *dst, off_t pos, off_t count) const
|
IFileDataContainer::off_t FileDataContainerCallbackStreamSeekable::InternalRead(std::byte *dst, off_t pos, off_t count) const
|
||||||
{
|
{
|
||||||
if(!stream.read)
|
if(!stream.read)
|
||||||
{
|
{
|
||||||
|
@ -710,7 +636,7 @@ bool FileDataContainerCallbackStream::InternalEof() const
|
||||||
return eof_reached;
|
return eof_reached;
|
||||||
}
|
}
|
||||||
|
|
||||||
IFileDataContainer::off_t FileDataContainerCallbackStream::InternalRead(mpt::byte *dst, off_t count) const
|
IFileDataContainer::off_t FileDataContainerCallbackStream::InternalRead(std::byte *dst, off_t count) const
|
||||||
{
|
{
|
||||||
if(eof_reached)
|
if(eof_reached)
|
||||||
{
|
{
|
||||||
|
@ -741,8 +667,5 @@ IFileDataContainer::off_t FileDataContainerCallbackStream::InternalRead(mpt::byt
|
||||||
#endif // MPT_FILEREADER_CALLBACK_STREAM
|
#endif // MPT_FILEREADER_CALLBACK_STREAM
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
OPENMPT_NAMESPACE_END
|
OPENMPT_NAMESPACE_END
|
||||||
|
|
|
@ -50,6 +50,8 @@ inline bool OffsetFits(IO::Offset off)
|
||||||
bool IsValid(std::ostream & f);
|
bool IsValid(std::ostream & f);
|
||||||
bool IsValid(std::istream & f);
|
bool IsValid(std::istream & f);
|
||||||
bool IsValid(std::iostream & f);
|
bool IsValid(std::iostream & f);
|
||||||
|
bool IsReadSeekable(std::istream& f);
|
||||||
|
bool IsWriteSeekable(std::ostream& f);
|
||||||
IO::Offset TellRead(std::istream & f);
|
IO::Offset TellRead(std::istream & f);
|
||||||
IO::Offset TellWrite(std::ostream & f);
|
IO::Offset TellWrite(std::ostream & f);
|
||||||
bool SeekBegin(std::ostream & f);
|
bool SeekBegin(std::ostream & f);
|
||||||
|
@ -64,8 +66,8 @@ bool SeekAbsolute(std::iostream & f, IO::Offset pos);
|
||||||
bool SeekRelative(std::ostream & f, IO::Offset off);
|
bool SeekRelative(std::ostream & f, IO::Offset off);
|
||||||
bool SeekRelative(std::istream & f, IO::Offset off);
|
bool SeekRelative(std::istream & f, IO::Offset off);
|
||||||
bool SeekRelative(std::iostream & f, IO::Offset off);
|
bool SeekRelative(std::iostream & f, IO::Offset off);
|
||||||
IO::Offset ReadRawImpl(std::istream & f, mpt::byte * data, std::size_t size);
|
IO::Offset ReadRawImpl(std::istream & f, mpt::byte_span data);
|
||||||
bool WriteRawImpl(std::ostream & f, const mpt::byte * data, std::size_t size);
|
bool WriteRawImpl(std::ostream & f, mpt::const_byte_span data);
|
||||||
bool IsEof(std::istream & f);
|
bool IsEof(std::istream & f);
|
||||||
bool Flush(std::ostream & f);
|
bool Flush(std::ostream & f);
|
||||||
|
|
||||||
|
@ -74,14 +76,16 @@ bool Flush(std::ostream & f);
|
||||||
template <typename Tfile> class WriteBuffer;
|
template <typename Tfile> class WriteBuffer;
|
||||||
|
|
||||||
template <typename Tfile> bool IsValid(WriteBuffer<Tfile> & f) { return IsValid(f.file()); }
|
template <typename Tfile> bool IsValid(WriteBuffer<Tfile> & f) { return IsValid(f.file()); }
|
||||||
|
template <typename Tfile> bool IsReadSeekable(WriteBuffer<Tfile> & f) { return IsReadSeekable(f.file()); }
|
||||||
|
template <typename Tfile> bool IsWriteSeekable(WriteBuffer<Tfile> & f) { return IsWriteSeekable(f.file()); }
|
||||||
template <typename Tfile> IO::Offset TellRead(WriteBuffer<Tfile> & f) { f.FlushLocal(); return TellRead(f.file()); }
|
template <typename Tfile> IO::Offset TellRead(WriteBuffer<Tfile> & f) { f.FlushLocal(); return TellRead(f.file()); }
|
||||||
template <typename Tfile> IO::Offset TellWrite(WriteBuffer<Tfile> & f) { return TellWrite(f.file()) + f.GetCurrentSize(); }
|
template <typename Tfile> IO::Offset TellWrite(WriteBuffer<Tfile> & f) { return TellWrite(f.file()) + f.GetCurrentSize(); }
|
||||||
template <typename Tfile> bool SeekBegin(WriteBuffer<Tfile> & f) { f.FlushLocal(); return SeekBegin(f.file()); }
|
template <typename Tfile> bool SeekBegin(WriteBuffer<Tfile> & f) { f.FlushLocal(); return SeekBegin(f.file()); }
|
||||||
template <typename Tfile> bool SeekEnd(WriteBuffer<Tfile> & f) { f.FlushLocal(); return SeekEnd(f.file()); }
|
template <typename Tfile> bool SeekEnd(WriteBuffer<Tfile> & f) { f.FlushLocal(); return SeekEnd(f.file()); }
|
||||||
template <typename Tfile> bool SeekAbsolute(WriteBuffer<Tfile> & f, IO::Offset pos) { return f.FlushLocal(); SeekAbsolute(f.file(), pos); }
|
template <typename Tfile> bool SeekAbsolute(WriteBuffer<Tfile> & f, IO::Offset pos) { f.FlushLocal(); return SeekAbsolute(f.file(), pos); }
|
||||||
template <typename Tfile> bool SeekRelative(WriteBuffer<Tfile> & f, IO::Offset off) { return f.FlushLocal(); SeekRelative(f.file(), off); }
|
template <typename Tfile> bool SeekRelative(WriteBuffer<Tfile> & f, IO::Offset off) { f.FlushLocal(); return SeekRelative(f.file(), off); }
|
||||||
template <typename Tfile> IO::Offset ReadRawImpl(WriteBuffer<Tfile> & f, mpt::byte * data, std::size_t size) { f.FlushLocal(); return ReadRawImpl(f.file(), data, size); }
|
template <typename Tfile> IO::Offset ReadRawImpl(WriteBuffer<Tfile> & f, mpt::byte_span data) { f.FlushLocal(); return ReadRawImpl(f.file(), data); }
|
||||||
template <typename Tfile> bool WriteRawImpl(WriteBuffer<Tfile> & f, const mpt::byte * data, std::size_t size) { return f.Write(mpt::as_span(data, size)); }
|
template <typename Tfile> bool WriteRawImpl(WriteBuffer<Tfile> & f, mpt::const_byte_span data) { return f.Write(data); }
|
||||||
template <typename Tfile> bool IsEof(WriteBuffer<Tfile> & f) { f.FlushLocal(); return IsEof(f.file()); }
|
template <typename Tfile> bool IsEof(WriteBuffer<Tfile> & f) { f.FlushLocal(); return IsEof(f.file()); }
|
||||||
template <typename Tfile> bool Flush(WriteBuffer<Tfile> & f) { f.FlushLocal(); return Flush(f.file()); }
|
template <typename Tfile> bool Flush(WriteBuffer<Tfile> & f) { f.FlushLocal(); return Flush(f.file()); }
|
||||||
|
|
||||||
|
@ -125,7 +129,7 @@ template <typename Tbyte> bool SeekRelative(std::pair<mpt::span<Tbyte>, IO::Offs
|
||||||
f.second += off;
|
f.second += off;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
template <typename Tbyte> IO::Offset ReadRawImpl(std::pair<mpt::span<Tbyte>, IO::Offset> & f, mpt::byte * data, std::size_t size)
|
template <typename Tbyte> IO::Offset ReadRawImpl(std::pair<mpt::span<Tbyte>, IO::Offset> & f, mpt::byte_span data)
|
||||||
{
|
{
|
||||||
if(f.second < 0)
|
if(f.second < 0)
|
||||||
{
|
{
|
||||||
|
@ -135,27 +139,27 @@ template <typename Tbyte> IO::Offset ReadRawImpl(std::pair<mpt::span<Tbyte>, IO:
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
std::size_t num = mpt::saturate_cast<std::size_t>(std::min<IO::Offset>(f.first.size() - f.second, size));
|
std::size_t num = mpt::saturate_cast<std::size_t>(std::min(static_cast<IO::Offset>(f.first.size()) - f.second, static_cast<IO::Offset>(data.size())));
|
||||||
std::copy(mpt::byte_cast<const mpt::byte*>(f.first.data() + f.second), mpt::byte_cast<const mpt::byte*>(f.first.data() + f.second + num), data);
|
std::copy(mpt::byte_cast<const std::byte*>(f.first.data() + f.second), mpt::byte_cast<const std::byte*>(f.first.data() + f.second + num), data.data());
|
||||||
f.second += num;
|
f.second += num;
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
template <typename Tbyte> bool WriteRawImpl(std::pair<mpt::span<Tbyte>, IO::Offset> & f, const mpt::byte * data, std::size_t size)
|
template <typename Tbyte> bool WriteRawImpl(std::pair<mpt::span<Tbyte>, IO::Offset> & f, mpt::const_byte_span data)
|
||||||
{
|
{
|
||||||
if(f.second < 0)
|
if(f.second < 0)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(f.second >= static_cast<IO::Offset>(f.first.size()))
|
if(f.second > static_cast<IO::Offset>(f.first.size()))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::size_t num = mpt::saturate_cast<std::size_t>(std::min<IO::Offset>(f.first.size() - f.second, size));
|
std::size_t num = mpt::saturate_cast<std::size_t>(std::min(static_cast<IO::Offset>(f.first.size()) - f.second, static_cast<IO::Offset>(data.size())));
|
||||||
if(num != size)
|
if(num != data.size())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::copy(data, data + num, mpt::byte_cast<mpt::byte*>(f.first.data() + f.second));
|
std::copy(data.data(), data.data() + num, mpt::byte_cast<std::byte*>(f.first.data() + f.second));
|
||||||
f.second += num;
|
f.second += num;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -165,7 +169,7 @@ template <typename Tbyte> bool IsEof(std::pair<mpt::span<Tbyte>, IO::Offset> & f
|
||||||
}
|
}
|
||||||
template <typename Tbyte> bool Flush(std::pair<mpt::span<Tbyte>, IO::Offset> & f)
|
template <typename Tbyte> bool Flush(std::pair<mpt::span<Tbyte>, IO::Offset> & f)
|
||||||
{
|
{
|
||||||
MPT_UNREFERENCED_PARAMTER(f);
|
MPT_UNREFERENCED_PARAMETER(f);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,25 +178,25 @@ template <typename Tbyte> bool Flush(std::pair<mpt::span<Tbyte>, IO::Offset> & f
|
||||||
template <typename Tbyte, typename Tfile>
|
template <typename Tbyte, typename Tfile>
|
||||||
inline IO::Offset ReadRaw(Tfile & f, Tbyte * data, std::size_t size)
|
inline IO::Offset ReadRaw(Tfile & f, Tbyte * data, std::size_t size)
|
||||||
{
|
{
|
||||||
return IO::ReadRawImpl(f, mpt::byte_cast<mpt::byte*>(data), size);
|
return IO::ReadRawImpl(f, mpt::as_span(mpt::byte_cast<std::byte*>(data), size));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Tbyte, typename Tfile>
|
template <typename Tbyte, typename Tfile>
|
||||||
inline IO::Offset ReadRaw(Tfile & f, mpt::span<Tbyte> data)
|
inline IO::Offset ReadRaw(Tfile & f, mpt::span<Tbyte> data)
|
||||||
{
|
{
|
||||||
return IO::ReadRawImpl(f, mpt::byte_cast<mpt::byte*>(data.data()), data.size());
|
return IO::ReadRawImpl(f, mpt::byte_cast<mpt::byte_span>(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Tbyte, typename Tfile>
|
template <typename Tbyte, typename Tfile>
|
||||||
inline bool WriteRaw(Tfile & f, const Tbyte * data, std::size_t size)
|
inline bool WriteRaw(Tfile & f, const Tbyte * data, std::size_t size)
|
||||||
{
|
{
|
||||||
return IO::WriteRawImpl(f, mpt::byte_cast<const mpt::byte*>(data), size);
|
return IO::WriteRawImpl(f, mpt::as_span(mpt::byte_cast<const std::byte*>(data), size));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Tbyte, typename Tfile>
|
template <typename Tbyte, typename Tfile>
|
||||||
inline bool WriteRaw(Tfile & f, mpt::span<Tbyte> data)
|
inline bool WriteRaw(Tfile & f, mpt::span<Tbyte> data)
|
||||||
{
|
{
|
||||||
return IO::WriteRawImpl(f, mpt::byte_cast<const mpt::byte*>(data.data()), data.size());
|
return IO::WriteRawImpl(f, mpt::byte_cast<mpt::const_byte_span>(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Tbinary, typename Tfile>
|
template <typename Tbinary, typename Tfile>
|
||||||
|
@ -210,7 +214,7 @@ inline bool Write(Tfile & f, const Tbinary & v)
|
||||||
template <typename Tbinary, typename Tfile>
|
template <typename Tbinary, typename Tfile>
|
||||||
inline bool Write(Tfile & f, const std::vector<Tbinary> & v)
|
inline bool Write(Tfile & f, const std::vector<Tbinary> & v)
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(mpt::is_binary_safe<Tbinary>::value);
|
static_assert(mpt::is_binary_safe<Tbinary>::value);
|
||||||
return IO::WriteRaw(f, mpt::as_raw_memory(v));
|
return IO::WriteRaw(f, mpt::as_raw_memory(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,17 +226,17 @@ inline bool WritePartial(Tfile & f, const T & v, size_t size = sizeof(T))
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Tfile>
|
template <typename Tfile>
|
||||||
inline bool ReadByte(Tfile & f, mpt::byte & v)
|
inline bool ReadByte(Tfile & f, std::byte & v)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
mpt::byte byte = mpt::as_byte(0);
|
std::byte byte = mpt::as_byte(0);
|
||||||
const IO::Offset readResult = IO::ReadRaw(f, &byte, sizeof(mpt::byte));
|
const IO::Offset readResult = IO::ReadRaw(f, &byte, sizeof(std::byte));
|
||||||
if(readResult < 0)
|
if(readResult < 0)
|
||||||
{
|
{
|
||||||
result = false;
|
result = false;
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
result = (static_cast<uint64>(readResult) == sizeof(mpt::byte));
|
result = (static_cast<uint64>(readResult) == sizeof(std::byte));
|
||||||
}
|
}
|
||||||
v = byte;
|
v = byte;
|
||||||
return result;
|
return result;
|
||||||
|
@ -242,7 +246,7 @@ template <typename T, typename Tfile>
|
||||||
inline bool ReadBinaryTruncatedLE(Tfile & f, T & v, std::size_t size)
|
inline bool ReadBinaryTruncatedLE(Tfile & f, T & v, std::size_t size)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
MPT_STATIC_ASSERT(std::numeric_limits<T>::is_integer);
|
static_assert(std::numeric_limits<T>::is_integer);
|
||||||
uint8 bytes[sizeof(T)];
|
uint8 bytes[sizeof(T)];
|
||||||
std::memset(bytes, 0, sizeof(T));
|
std::memset(bytes, 0, sizeof(T));
|
||||||
const IO::Offset readResult = IO::ReadRaw(f, bytes, std::min(size, sizeof(T)));
|
const IO::Offset readResult = IO::ReadRaw(f, bytes, std::min(size, sizeof(T)));
|
||||||
|
@ -263,7 +267,7 @@ template <typename T, typename Tfile>
|
||||||
inline bool ReadIntLE(Tfile & f, T & v)
|
inline bool ReadIntLE(Tfile & f, T & v)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
STATIC_ASSERT(std::numeric_limits<T>::is_integer);
|
static_assert(std::numeric_limits<T>::is_integer);
|
||||||
uint8 bytes[sizeof(T)];
|
uint8 bytes[sizeof(T)];
|
||||||
std::memset(bytes, 0, sizeof(T));
|
std::memset(bytes, 0, sizeof(T));
|
||||||
const IO::Offset readResult = IO::ReadRaw(f, bytes, sizeof(T));
|
const IO::Offset readResult = IO::ReadRaw(f, bytes, sizeof(T));
|
||||||
|
@ -284,7 +288,7 @@ template <typename T, typename Tfile>
|
||||||
inline bool ReadIntBE(Tfile & f, T & v)
|
inline bool ReadIntBE(Tfile & f, T & v)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
STATIC_ASSERT(std::numeric_limits<T>::is_integer);
|
static_assert(std::numeric_limits<T>::is_integer);
|
||||||
uint8 bytes[sizeof(T)];
|
uint8 bytes[sizeof(T)];
|
||||||
std::memset(bytes, 0, sizeof(T));
|
std::memset(bytes, 0, sizeof(T));
|
||||||
const IO::Offset readResult = IO::ReadRaw(f, bytes, sizeof(T));
|
const IO::Offset readResult = IO::ReadRaw(f, bytes, sizeof(T));
|
||||||
|
@ -364,7 +368,7 @@ inline bool ReadAdaptiveInt64LE(Tfile & f, uint64 & v)
|
||||||
template <typename Tsize, typename Tfile>
|
template <typename Tsize, typename Tfile>
|
||||||
inline bool ReadSizedStringLE(Tfile & f, std::string & str, Tsize maxSize = std::numeric_limits<Tsize>::max())
|
inline bool ReadSizedStringLE(Tfile & f, std::string & str, Tsize maxSize = std::numeric_limits<Tsize>::max())
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(std::numeric_limits<Tsize>::is_integer);
|
static_assert(std::numeric_limits<Tsize>::is_integer);
|
||||||
str.clear();
|
str.clear();
|
||||||
Tsize size = 0;
|
Tsize size = 0;
|
||||||
if(!mpt::IO::ReadIntLE(f, size))
|
if(!mpt::IO::ReadIntLE(f, size))
|
||||||
|
@ -391,14 +395,14 @@ inline bool ReadSizedStringLE(Tfile & f, std::string & str, Tsize maxSize = std:
|
||||||
template <typename T, typename Tfile>
|
template <typename T, typename Tfile>
|
||||||
inline bool WriteIntLE(Tfile & f, const T v)
|
inline bool WriteIntLE(Tfile & f, const T v)
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(std::numeric_limits<T>::is_integer);
|
static_assert(std::numeric_limits<T>::is_integer);
|
||||||
return IO::Write(f, mpt::as_le(v));
|
return IO::Write(f, mpt::as_le(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename Tfile>
|
template <typename T, typename Tfile>
|
||||||
inline bool WriteIntBE(Tfile & f, const T v)
|
inline bool WriteIntBE(Tfile & f, const T v)
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(std::numeric_limits<T>::is_integer);
|
static_assert(std::numeric_limits<T>::is_integer);
|
||||||
return IO::Write(f, mpt::as_be(v));
|
return IO::Write(f, mpt::as_be(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -448,10 +452,10 @@ inline bool WriteAdaptiveInt32LE(Tfile & f, const uint32 v, std::size_t fixedSiz
|
||||||
} else if(v < 0x400000 && minSize <= 3 && 3 <= maxSize)
|
} else if(v < 0x400000 && minSize <= 3 && 3 <= maxSize)
|
||||||
{
|
{
|
||||||
uint32 value = static_cast<uint32>(v << 2) | 0x02;
|
uint32 value = static_cast<uint32>(v << 2) | 0x02;
|
||||||
mpt::byte bytes[3];
|
std::byte bytes[3];
|
||||||
bytes[0] = static_cast<mpt::byte>(value >> 0);
|
bytes[0] = static_cast<std::byte>(value >> 0);
|
||||||
bytes[1] = static_cast<mpt::byte>(value >> 8);
|
bytes[1] = static_cast<std::byte>(value >> 8);
|
||||||
bytes[2] = static_cast<mpt::byte>(value >> 16);
|
bytes[2] = static_cast<std::byte>(value >> 16);
|
||||||
return IO::WriteRaw(f, bytes, 3);
|
return IO::WriteRaw(f, bytes, 3);
|
||||||
} else if(v < 0x40000000 && minSize <= 4 && 4 <= maxSize)
|
} else if(v < 0x40000000 && minSize <= 4 && 4 <= maxSize)
|
||||||
{
|
{
|
||||||
|
@ -498,19 +502,19 @@ inline bool WriteAdaptiveInt64LE(Tfile & f, const uint64 v, std::size_t fixedSiz
|
||||||
template <typename Tfile, typename T>
|
template <typename Tfile, typename T>
|
||||||
bool WriteVarInt(Tfile & f, const T v, size_t *bytesWritten = nullptr)
|
bool WriteVarInt(Tfile & f, const T v, size_t *bytesWritten = nullptr)
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(std::numeric_limits<T>::is_integer);
|
static_assert(std::numeric_limits<T>::is_integer);
|
||||||
STATIC_ASSERT(!std::numeric_limits<T>::is_signed);
|
static_assert(!std::numeric_limits<T>::is_signed);
|
||||||
mpt::byte out[(sizeof(T) * 8 + 6) / 7];
|
std::byte out[(sizeof(T) * 8 + 6) / 7];
|
||||||
size_t numBytes = 0;
|
size_t numBytes = 0;
|
||||||
for(uint32 n = (sizeof(T) * 8) / 7; n > 0; n--)
|
for(uint32 n = (sizeof(T) * 8) / 7; n > 0; n--)
|
||||||
{
|
{
|
||||||
if(v >= (static_cast<T>(1) << (n * 7u)))
|
if(v >= (static_cast<T>(1) << (n * 7u)))
|
||||||
{
|
{
|
||||||
out[numBytes++] = static_cast<mpt::byte>(((v >> (n * 7u)) & 0x7F) | 0x80);
|
out[numBytes++] = static_cast<std::byte>(((v >> (n * 7u)) & 0x7F) | 0x80);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out[numBytes++] = static_cast<mpt::byte>(v & 0x7F);
|
out[numBytes++] = static_cast<std::byte>(v & 0x7F);
|
||||||
MPT_ASSERT(numBytes <= mpt::size(out));
|
MPT_ASSERT(numBytes <= std::size(out));
|
||||||
if(bytesWritten != nullptr) *bytesWritten = numBytes;
|
if(bytesWritten != nullptr) *bytesWritten = numBytes;
|
||||||
return mpt::IO::WriteRaw(f, out, numBytes);
|
return mpt::IO::WriteRaw(f, out, numBytes);
|
||||||
}
|
}
|
||||||
|
@ -518,7 +522,7 @@ bool WriteVarInt(Tfile & f, const T v, size_t *bytesWritten = nullptr)
|
||||||
template <typename Tsize, typename Tfile>
|
template <typename Tsize, typename Tfile>
|
||||||
inline bool WriteSizedStringLE(Tfile & f, const std::string & str)
|
inline bool WriteSizedStringLE(Tfile & f, const std::string & str)
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(std::numeric_limits<Tsize>::is_integer);
|
static_assert(std::numeric_limits<Tsize>::is_integer);
|
||||||
if(str.size() > std::numeric_limits<Tsize>::max())
|
if(str.size() > std::numeric_limits<Tsize>::max())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -675,8 +679,6 @@ public:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(MPT_FILEREADER_STD_ISTREAM)
|
|
||||||
|
|
||||||
class IFileDataContainer {
|
class IFileDataContainer {
|
||||||
public:
|
public:
|
||||||
typedef std::size_t off_t;
|
typedef std::size_t off_t;
|
||||||
|
@ -690,9 +692,9 @@ public:
|
||||||
virtual bool IsValid() const = 0;
|
virtual bool IsValid() const = 0;
|
||||||
virtual bool HasFastGetLength() const = 0;
|
virtual bool HasFastGetLength() const = 0;
|
||||||
virtual bool HasPinnedView() const = 0;
|
virtual bool HasPinnedView() const = 0;
|
||||||
virtual const mpt::byte *GetRawData() const = 0;
|
virtual const std::byte *GetRawData() const = 0;
|
||||||
virtual off_t GetLength() const = 0;
|
virtual off_t GetLength() const = 0;
|
||||||
virtual off_t Read(mpt::byte *dst, off_t pos, off_t count) const = 0;
|
virtual off_t Read(std::byte *dst, off_t pos, off_t count) const = 0;
|
||||||
|
|
||||||
virtual off_t Read(off_t pos, mpt::byte_span dst) const
|
virtual off_t Read(off_t pos, mpt::byte_span dst) const
|
||||||
{
|
{
|
||||||
|
@ -720,7 +722,7 @@ public:
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return std::min<off_t>(length, dataLength - pos);
|
return std::min(length, dataLength - pos);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -744,7 +746,7 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mpt::byte *GetRawData() const override
|
const std::byte *GetRawData() const override
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -753,7 +755,7 @@ public:
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
off_t Read(mpt::byte * /*dst*/, off_t /*pos*/, off_t /*count*/) const override
|
off_t Read(std::byte * /*dst*/, off_t /*pos*/, off_t /*count*/) const override
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -781,7 +783,7 @@ public:
|
||||||
{
|
{
|
||||||
return data->HasPinnedView();
|
return data->HasPinnedView();
|
||||||
}
|
}
|
||||||
const mpt::byte *GetRawData() const override
|
const std::byte *GetRawData() const override
|
||||||
{
|
{
|
||||||
return data->GetRawData() + dataOffset;
|
return data->GetRawData() + dataOffset;
|
||||||
}
|
}
|
||||||
|
@ -789,7 +791,7 @@ public:
|
||||||
{
|
{
|
||||||
return dataLength;
|
return dataLength;
|
||||||
}
|
}
|
||||||
off_t Read(mpt::byte *dst, off_t pos, off_t count) const override
|
off_t Read(std::byte *dst, off_t pos, off_t count) const override
|
||||||
{
|
{
|
||||||
if(pos >= dataLength)
|
if(pos >= dataLength)
|
||||||
{
|
{
|
||||||
|
@ -827,11 +829,36 @@ private:
|
||||||
off_t streamLength;
|
off_t streamLength;
|
||||||
|
|
||||||
mutable bool cached;
|
mutable bool cached;
|
||||||
mutable std::vector<mpt::byte> cache;
|
mutable std::vector<std::byte> cache;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
mutable bool m_Buffered;
|
||||||
|
enum : std::size_t {
|
||||||
|
CHUNK_SIZE = mpt::IO::BUFFERSIZE_SMALL,
|
||||||
|
BUFFER_SIZE = mpt::IO::BUFFERSIZE_NORMAL
|
||||||
|
};
|
||||||
|
enum : std::size_t {
|
||||||
|
NUM_CHUNKS = BUFFER_SIZE / CHUNK_SIZE
|
||||||
|
};
|
||||||
|
struct chunk_info {
|
||||||
|
off_t ChunkOffset = 0;
|
||||||
|
off_t ChunkLength = 0;
|
||||||
|
bool ChunkValid = false;
|
||||||
|
};
|
||||||
|
mutable std::vector<std::byte> m_Buffer;
|
||||||
|
mpt::byte_span chunk_data(std::size_t chunkIndex) const
|
||||||
|
{
|
||||||
|
return mpt::byte_span(m_Buffer.data() + (chunkIndex * CHUNK_SIZE), CHUNK_SIZE);
|
||||||
|
}
|
||||||
|
mutable std::array<chunk_info, NUM_CHUNKS> m_ChunkInfo;
|
||||||
|
mutable std::array<std::size_t, NUM_CHUNKS> m_ChunkIndexLRU;
|
||||||
|
|
||||||
|
std::size_t InternalFillPageAndReturnIndex(off_t pos) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
FileDataContainerSeekable(off_t length);
|
FileDataContainerSeekable(off_t length, bool buffered);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -842,13 +869,15 @@ public:
|
||||||
bool IsValid() const override;
|
bool IsValid() const override;
|
||||||
bool HasFastGetLength() const override;
|
bool HasFastGetLength() const override;
|
||||||
bool HasPinnedView() const override;
|
bool HasPinnedView() const override;
|
||||||
const mpt::byte *GetRawData() const override;
|
const std::byte *GetRawData() const override;
|
||||||
off_t GetLength() const override;
|
off_t GetLength() const override;
|
||||||
off_t Read(mpt::byte *dst, off_t pos, off_t count) const override;
|
off_t Read(std::byte *dst, off_t pos, off_t count) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
virtual off_t InternalRead(mpt::byte *dst, off_t pos, off_t count) const = 0;
|
off_t InternalReadBuffered(std::byte* dst, off_t pos, off_t count) const;
|
||||||
|
|
||||||
|
virtual off_t InternalRead(std::byte *dst, off_t pos, off_t count) const = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -868,7 +897,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
off_t InternalRead(mpt::byte *dst, off_t pos, off_t count) const override;
|
off_t InternalRead(std::byte *dst, off_t pos, off_t count) const override;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -877,7 +906,7 @@ class FileDataContainerUnseekable : public IFileDataContainer {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
mutable std::vector<mpt::byte> cache;
|
mutable std::vector<std::byte> cache;
|
||||||
mutable std::size_t cachesize;
|
mutable std::size_t cachesize;
|
||||||
mutable bool streamFullyCached;
|
mutable bool streamFullyCached;
|
||||||
|
|
||||||
|
@ -898,23 +927,23 @@ private:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void ReadCached(mpt::byte *dst, off_t pos, off_t count) const;
|
void ReadCached(std::byte *dst, off_t pos, off_t count) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
bool IsValid() const override;
|
bool IsValid() const override;
|
||||||
bool HasFastGetLength() const override;
|
bool HasFastGetLength() const override;
|
||||||
bool HasPinnedView() const override;
|
bool HasPinnedView() const override;
|
||||||
const mpt::byte *GetRawData() const override;
|
const std::byte *GetRawData() const override;
|
||||||
off_t GetLength() const override;
|
off_t GetLength() const override;
|
||||||
off_t Read(mpt::byte *dst, off_t pos, off_t count) const override;
|
off_t Read(std::byte *dst, off_t pos, off_t count) const override;
|
||||||
bool CanRead(off_t pos, off_t length) const override;
|
bool CanRead(off_t pos, off_t length) const override;
|
||||||
off_t GetReadableLength(off_t pos, off_t length) const override;
|
off_t GetReadableLength(off_t pos, off_t length) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
virtual bool InternalEof() const = 0;
|
virtual bool InternalEof() const = 0;
|
||||||
virtual off_t InternalRead(mpt::byte *dst, off_t count) const = 0;
|
virtual off_t InternalRead(std::byte *dst, off_t count) const = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -932,7 +961,7 @@ public:
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool InternalEof() const override;
|
bool InternalEof() const override;
|
||||||
off_t InternalRead(mpt::byte *dst, off_t count) const override;
|
off_t InternalRead(std::byte *dst, off_t count) const override;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -963,7 +992,7 @@ public:
|
||||||
static off_t GetLength(CallbackStream stream);
|
static off_t GetLength(CallbackStream stream);
|
||||||
FileDataContainerCallbackStreamSeekable(CallbackStream s);
|
FileDataContainerCallbackStreamSeekable(CallbackStream s);
|
||||||
private:
|
private:
|
||||||
off_t InternalRead(mpt::byte *dst, off_t pos, off_t count) const override;
|
off_t InternalRead(std::byte *dst, off_t pos, off_t count) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -976,36 +1005,20 @@ public:
|
||||||
FileDataContainerCallbackStream(CallbackStream s);
|
FileDataContainerCallbackStream(CallbackStream s);
|
||||||
private:
|
private:
|
||||||
bool InternalEof() const override;
|
bool InternalEof() const override;
|
||||||
off_t InternalRead(mpt::byte *dst, off_t count) const override;
|
off_t InternalRead(std::byte *dst, off_t count) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // MPT_FILEREADER_CALLBACK_STREAM
|
#endif // MPT_FILEREADER_CALLBACK_STREAM
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
class FileDataContainerMemory
|
class FileDataContainerMemory
|
||||||
#if defined(MPT_FILEREADER_STD_ISTREAM)
|
|
||||||
: public IFileDataContainer
|
: public IFileDataContainer
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
|
|
||||||
#if defined(MPT_FILEREADER_STD_ISTREAM)
|
|
||||||
#define MPT_FILEDATACONTAINERMEMORY_OVERRIDE override
|
|
||||||
#else
|
|
||||||
#define MPT_FILEDATACONTAINERMEMORY_OVERRIDE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(MPT_FILEREADER_STD_ISTREAM)
|
|
||||||
public:
|
|
||||||
typedef std::size_t off_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
const mpt::byte *streamData; // Pointer to memory-mapped file
|
const std::byte *streamData; // Pointer to memory-mapped file
|
||||||
off_t streamLength; // Size of memory-mapped file in bytes
|
off_t streamLength; // Size of memory-mapped file in bytes
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -1014,48 +1027,48 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
bool IsValid() const MPT_FILEDATACONTAINERMEMORY_OVERRIDE
|
bool IsValid() const override
|
||||||
{
|
{
|
||||||
return streamData != nullptr;
|
return streamData != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HasFastGetLength() const MPT_FILEDATACONTAINERMEMORY_OVERRIDE
|
bool HasFastGetLength() const override
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HasPinnedView() const MPT_FILEDATACONTAINERMEMORY_OVERRIDE
|
bool HasPinnedView() const override
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mpt::byte *GetRawData() const MPT_FILEDATACONTAINERMEMORY_OVERRIDE
|
const std::byte *GetRawData() const override
|
||||||
{
|
{
|
||||||
return streamData;
|
return streamData;
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t GetLength() const MPT_FILEDATACONTAINERMEMORY_OVERRIDE
|
off_t GetLength() const override
|
||||||
{
|
{
|
||||||
return streamLength;
|
return streamLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t Read(mpt::byte *dst, off_t pos, off_t count) const MPT_FILEDATACONTAINERMEMORY_OVERRIDE
|
off_t Read(std::byte *dst, off_t pos, off_t count) const override
|
||||||
{
|
{
|
||||||
if(pos >= streamLength)
|
if(pos >= streamLength)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
off_t avail = std::min<off_t>(streamLength - pos, count);
|
off_t avail = std::min(streamLength - pos, count);
|
||||||
std::copy(streamData + pos, streamData + pos + avail, dst);
|
std::copy(streamData + pos, streamData + pos + avail, dst);
|
||||||
return avail;
|
return avail;
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t Read(off_t pos, mpt::byte_span dst) const MPT_FILEDATACONTAINERMEMORY_OVERRIDE
|
off_t Read(off_t pos, mpt::byte_span dst) const override
|
||||||
{
|
{
|
||||||
return Read(dst.data(), pos, dst.size());
|
return Read(dst.data(), pos, dst.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CanRead(off_t pos, off_t length) const MPT_FILEDATACONTAINERMEMORY_OVERRIDE
|
bool CanRead(off_t pos, off_t length) const override
|
||||||
{
|
{
|
||||||
if((pos == streamLength) && (length == 0))
|
if((pos == streamLength) && (length == 0))
|
||||||
{
|
{
|
||||||
|
@ -1068,13 +1081,13 @@ public:
|
||||||
return (length <= streamLength - pos);
|
return (length <= streamLength - pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t GetReadableLength(off_t pos, off_t length) const MPT_FILEDATACONTAINERMEMORY_OVERRIDE
|
off_t GetReadableLength(off_t pos, off_t length) const override
|
||||||
{
|
{
|
||||||
if(pos >= streamLength)
|
if(pos >= streamLength)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return std::min<off_t>(length, streamLength - pos);
|
return std::min(length, streamLength - pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -100,7 +100,7 @@ public:
|
||||||
if(WindowsVersion.IsAtLeast(mpt::Windows::Version::Win8))
|
if(WindowsVersion.IsAtLeast(mpt::Windows::Version::Win8))
|
||||||
{
|
{
|
||||||
hasKB2533623 = true;
|
hasKB2533623 = true;
|
||||||
} else if(WindowsVersion.IsAtLeast(mpt::Windows::Version::WinVista))
|
} else
|
||||||
{
|
{
|
||||||
HMODULE hKernel32DLL = LoadLibraryW(L"kernel32.dll");
|
HMODULE hKernel32DLL = LoadLibraryW(L"kernel32.dll");
|
||||||
if(hKernel32DLL)
|
if(hKernel32DLL)
|
||||||
|
@ -133,7 +133,7 @@ public:
|
||||||
// Just rely on the default search path here.
|
// Just rely on the default search path here.
|
||||||
case mpt::LibrarySearchPathApplication:
|
case mpt::LibrarySearchPathApplication:
|
||||||
{
|
{
|
||||||
const mpt::PathString dllPath = mpt::GetAppPath();
|
const mpt::PathString dllPath = mpt::GetExecutablePath();
|
||||||
if(!dllPath.empty() && mpt::PathIsAbsolute(dllPath) && dllPath.IsDirectory())
|
if(!dllPath.empty() && mpt::PathIsAbsolute(dllPath) && dllPath.IsDirectory())
|
||||||
{
|
{
|
||||||
hModule = LoadLibrary((dllPath + path.GetFileName()).AsNative().c_str());
|
hModule = LoadLibrary((dllPath + path.GetFileName()).AsNative().c_str());
|
||||||
|
@ -165,7 +165,7 @@ public:
|
||||||
break;
|
break;
|
||||||
case mpt::LibrarySearchPathApplication:
|
case mpt::LibrarySearchPathApplication:
|
||||||
{
|
{
|
||||||
const mpt::PathString dllPath = mpt::GetAppPath();
|
const mpt::PathString dllPath = mpt::GetExecutablePath();
|
||||||
if(!dllPath.empty() && mpt::PathIsAbsolute(dllPath) && dllPath.IsDirectory())
|
if(!dllPath.empty() && mpt::PathIsAbsolute(dllPath) && dllPath.IsDirectory())
|
||||||
{
|
{
|
||||||
hModule = LoadLibrary((dllPath + path.GetFileName()).AsNative().c_str());
|
hModule = LoadLibrary((dllPath + path.GetFileName()).AsNative().c_str());
|
||||||
|
@ -194,6 +194,10 @@ public:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LibraryHandle(const LibraryHandle &) = delete;
|
||||||
|
|
||||||
|
LibraryHandle & operator=(const LibraryHandle &) = delete;
|
||||||
|
|
||||||
~LibraryHandle()
|
~LibraryHandle()
|
||||||
{
|
{
|
||||||
if(IsValid())
|
if(IsValid())
|
||||||
|
@ -237,6 +241,10 @@ public:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LibraryHandle(const LibraryHandle &) = delete;
|
||||||
|
|
||||||
|
LibraryHandle & operator=(const LibraryHandle &) = delete;
|
||||||
|
|
||||||
~LibraryHandle()
|
~LibraryHandle()
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -287,6 +295,10 @@ public:
|
||||||
handle = lt_dlopenext(path.GetFileName().AsNative().c_str());
|
handle = lt_dlopenext(path.GetFileName().AsNative().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LibraryHandle(const LibraryHandle &) = delete;
|
||||||
|
|
||||||
|
LibraryHandle & operator=(const LibraryHandle &) = delete;
|
||||||
|
|
||||||
~LibraryHandle()
|
~LibraryHandle()
|
||||||
{
|
{
|
||||||
if(IsValid())
|
if(IsValid())
|
||||||
|
@ -338,6 +350,10 @@ public:
|
||||||
handle = dlopen(path.GetFileName().AsNative().c_str(), RTLD_NOW);
|
handle = dlopen(path.GetFileName().AsNative().c_str(), RTLD_NOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LibraryHandle(const LibraryHandle &) = delete;
|
||||||
|
|
||||||
|
LibraryHandle & operator=(const LibraryHandle &) = delete;
|
||||||
|
|
||||||
~LibraryHandle()
|
~LibraryHandle()
|
||||||
{
|
{
|
||||||
if(IsValid())
|
if(IsValid())
|
||||||
|
@ -381,6 +397,10 @@ public:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LibraryHandle(const LibraryHandle &) = delete;
|
||||||
|
|
||||||
|
LibraryHandle & operator=(const LibraryHandle &) = delete;
|
||||||
|
|
||||||
~LibraryHandle()
|
~LibraryHandle()
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -104,7 +104,7 @@ public:
|
||||||
#if !(MPT_OS_WINDOWS && MPT_COMPILER_GCC)
|
#if !(MPT_OS_WINDOWS && MPT_COMPILER_GCC)
|
||||||
// MinGW64 std::is_function is always false for non __cdecl functions.
|
// MinGW64 std::is_function is always false for non __cdecl functions.
|
||||||
// See https://connect.microsoft.com/VisualStudio/feedback/details/774720/stl-is-function-bug .
|
// See https://connect.microsoft.com/VisualStudio/feedback/details/774720/stl-is-function-bug .
|
||||||
STATIC_ASSERT(std::is_function<Tfunc>::value);
|
static_assert(std::is_function<Tfunc>::value);
|
||||||
#endif
|
#endif
|
||||||
const FuncPtr addr = GetProcAddress(symbol);
|
const FuncPtr addr = GetProcAddress(symbol);
|
||||||
f = reinterpret_cast<Tfunc*>(addr);
|
f = reinterpret_cast<Tfunc*>(addr);
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <bit>
|
#include <bit>
|
||||||
#endif
|
#endif
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
@ -36,8 +37,8 @@ namespace mpt {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef mpt::span<mpt::byte> byte_span;
|
typedef mpt::span<std::byte> byte_span;
|
||||||
typedef mpt::span<const mpt::byte> const_byte_span;
|
typedef mpt::span<const std::byte> const_byte_span;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -49,19 +50,15 @@ typedef mpt::span<const mpt::byte> const_byte_span;
|
||||||
template <typename T> struct is_byte_castable : public std::false_type { };
|
template <typename T> struct is_byte_castable : public std::false_type { };
|
||||||
template <> struct is_byte_castable<char> : public std::true_type { };
|
template <> struct is_byte_castable<char> : public std::true_type { };
|
||||||
template <> struct is_byte_castable<unsigned char> : public std::true_type { };
|
template <> struct is_byte_castable<unsigned char> : public std::true_type { };
|
||||||
#if MPT_BYTE_IS_STD_BYTE
|
template <> struct is_byte_castable<std::byte> : public std::true_type { };
|
||||||
template <> struct is_byte_castable<mpt::byte> : public std::true_type { };
|
|
||||||
#endif
|
|
||||||
template <> struct is_byte_castable<const char> : public std::true_type { };
|
template <> struct is_byte_castable<const char> : public std::true_type { };
|
||||||
template <> struct is_byte_castable<const unsigned char> : public std::true_type { };
|
template <> struct is_byte_castable<const unsigned char> : public std::true_type { };
|
||||||
#if MPT_BYTE_IS_STD_BYTE
|
template <> struct is_byte_castable<const std::byte> : public std::true_type { };
|
||||||
template <> struct is_byte_castable<const mpt::byte> : public std::true_type { };
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
template <typename T> struct is_byte : public std::false_type { };
|
template <typename T> struct is_byte : public std::false_type { };
|
||||||
template <> struct is_byte<mpt::byte> : public std::true_type { };
|
template <> struct is_byte<std::byte> : public std::true_type { };
|
||||||
template <> struct is_byte<const mpt::byte> : public std::true_type { };
|
template <> struct is_byte<const std::byte> : public std::true_type { };
|
||||||
|
|
||||||
|
|
||||||
// Tell which types are safe to binary write into files.
|
// Tell which types are safe to binary write into files.
|
||||||
|
@ -74,9 +71,7 @@ template <typename T> struct is_binary_safe : public std::false_type { };
|
||||||
template <> struct is_binary_safe<char> : public std::true_type { };
|
template <> struct is_binary_safe<char> : public std::true_type { };
|
||||||
template <> struct is_binary_safe<uint8> : public std::true_type { };
|
template <> struct is_binary_safe<uint8> : public std::true_type { };
|
||||||
template <> struct is_binary_safe<int8> : public std::true_type { };
|
template <> struct is_binary_safe<int8> : public std::true_type { };
|
||||||
#if MPT_BYTE_IS_STD_BYTE
|
template <> struct is_binary_safe<std::byte> : public std::true_type { };
|
||||||
template <> struct is_binary_safe<mpt::byte> : public std::true_type { };
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Generic Specialization for arrays.
|
// Generic Specialization for arrays.
|
||||||
template <typename T, std::size_t N> struct is_binary_safe<T[N]> : public is_binary_safe<T> { };
|
template <typename T, std::size_t N> struct is_binary_safe<T[N]> : public is_binary_safe<T> { };
|
||||||
|
@ -88,9 +83,9 @@ template <typename T, std::size_t N> struct is_binary_safe<const std::array<T, N
|
||||||
} // namespace mpt
|
} // namespace mpt
|
||||||
|
|
||||||
#define MPT_BINARY_STRUCT(type, size) \
|
#define MPT_BINARY_STRUCT(type, size) \
|
||||||
MPT_STATIC_ASSERT(sizeof( type ) == (size) ); \
|
static_assert(sizeof( type ) == (size) ); \
|
||||||
MPT_STATIC_ASSERT(alignof( type ) == 1); \
|
static_assert(alignof( type ) == 1); \
|
||||||
MPT_STATIC_ASSERT(std::is_standard_layout< type >::value); \
|
static_assert(std::is_standard_layout< type >::value); \
|
||||||
namespace mpt { \
|
namespace mpt { \
|
||||||
template <> struct is_binary_safe< type > : public std::true_type { }; \
|
template <> struct is_binary_safe< type > : public std::true_type { }; \
|
||||||
} \
|
} \
|
||||||
|
@ -122,7 +117,7 @@ struct value_initializer<T[N]>
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline void Clear(T & x)
|
inline void Clear(T & x)
|
||||||
{
|
{
|
||||||
MPT_STATIC_ASSERT(!std::is_pointer<T>::value);
|
static_assert(!std::is_pointer<T>::value);
|
||||||
value_initializer<T>()(x);
|
value_initializer<T>()(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,13 +127,8 @@ template <class T>
|
||||||
inline void MemsetZero(T &a)
|
inline void MemsetZero(T &a)
|
||||||
{
|
{
|
||||||
static_assert(std::is_pointer<T>::value == false, "Won't memset pointers.");
|
static_assert(std::is_pointer<T>::value == false, "Won't memset pointers.");
|
||||||
#if MPT_GCC_BEFORE(5,1,0) || (MPT_COMPILER_CLANG && defined(__GLIBCXX__))
|
static_assert(std::is_standard_layout<T>::value);
|
||||||
MPT_STATIC_ASSERT(std::is_standard_layout<T>::value);
|
static_assert((std::is_trivially_default_constructible<T>::value && std::is_trivially_copyable<T>::value) || mpt::is_binary_safe<T>::value);
|
||||||
MPT_STATIC_ASSERT(std::is_trivial<T>::value || mpt::is_binary_safe<T>::value); // approximation
|
|
||||||
#else // default
|
|
||||||
MPT_STATIC_ASSERT(std::is_standard_layout<T>::value);
|
|
||||||
MPT_STATIC_ASSERT((std::is_trivially_default_constructible<T>::value && std::is_trivially_copyable<T>::value) || mpt::is_binary_safe<T>::value); // C++11, but not supported on most compilers we care about
|
|
||||||
#endif
|
|
||||||
std::memset(&a, 0, sizeof(T));
|
std::memset(&a, 0, sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,39 +142,13 @@ namespace mpt {
|
||||||
using std::bit_cast;
|
using std::bit_cast;
|
||||||
#else
|
#else
|
||||||
// C++2a compatible bit_cast.
|
// C++2a compatible bit_cast.
|
||||||
// See <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0476r1.html>.
|
// Not implementing constexpr because this is not easily possible pre C++20.
|
||||||
// Not implementing constexpr because this is not easily possible pre C++2a.
|
|
||||||
template <typename Tdst, typename Tsrc>
|
template <typename Tdst, typename Tsrc>
|
||||||
MPT_FORCEINLINE Tdst bit_cast(const Tsrc & src) noexcept
|
MPT_FORCEINLINE typename std::enable_if<(sizeof(Tdst) == sizeof(Tsrc)) && std::is_trivially_copyable<Tsrc>::value && std::is_trivially_copyable<Tdst>::value, Tdst>::type bit_cast(const Tsrc & src) noexcept
|
||||||
{
|
{
|
||||||
MPT_STATIC_ASSERT(sizeof(Tdst) == sizeof(Tsrc));
|
Tdst dst{};
|
||||||
#if MPT_GCC_BEFORE(5,1,0) || (MPT_COMPILER_CLANG && defined(__GLIBCXX__))
|
std::memcpy(&dst, &src, sizeof(Tdst));
|
||||||
MPT_STATIC_ASSERT(std::is_trivial<Tdst>::value); // approximation
|
return dst;
|
||||||
MPT_STATIC_ASSERT(std::is_trivial<Tsrc>::value); // approximation
|
|
||||||
#else // default
|
|
||||||
MPT_STATIC_ASSERT(std::is_trivially_copyable<Tdst>::value);
|
|
||||||
MPT_STATIC_ASSERT(std::is_trivially_copyable<Tsrc>::value);
|
|
||||||
#endif
|
|
||||||
#if MPT_COMPILER_GCC || MPT_COMPILER_MSVC
|
|
||||||
// Compiler supports type-punning through unions. This is not stricly standard-conforming.
|
|
||||||
// For GCC, this is documented, for MSVC this is apparently not documented, but we assume it.
|
|
||||||
union {
|
|
||||||
Tsrc src;
|
|
||||||
Tdst dst;
|
|
||||||
} conv;
|
|
||||||
conv.src = src;
|
|
||||||
return conv.dst;
|
|
||||||
#else // MPT_COMPILER
|
|
||||||
// Compiler does not support type-punning through unions. std::memcpy is used instead.
|
|
||||||
// This is the safe fallback and strictly standard-conforming.
|
|
||||||
// Another standard-compliant alternative would be casting pointers to a character type pointer.
|
|
||||||
// This results in rather unreadable code and,
|
|
||||||
// in most cases, compilers generate better code by just inlining the memcpy anyway.
|
|
||||||
// (see <http://blog.regehr.org/archives/959>).
|
|
||||||
Tdst dst{};
|
|
||||||
std::memcpy(&dst, &src, sizeof(Tdst));
|
|
||||||
return dst;
|
|
||||||
#endif // MPT_COMPILER
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -195,12 +159,12 @@ struct byte_cast_impl
|
||||||
{
|
{
|
||||||
inline Tdst operator () (Tsrc src) const
|
inline Tdst operator () (Tsrc src) const
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(sizeof(Tsrc) == sizeof(mpt::byte));
|
static_assert(sizeof(Tsrc) == sizeof(std::byte));
|
||||||
STATIC_ASSERT(sizeof(Tdst) == sizeof(mpt::byte));
|
static_assert(sizeof(Tdst) == sizeof(std::byte));
|
||||||
// not checking is_byte_castable here because we are actually
|
// not checking is_byte_castable here because we are actually
|
||||||
// doing a static_cast and converting the value
|
// doing a static_cast and converting the value
|
||||||
STATIC_ASSERT(std::is_integral<Tsrc>::value || mpt::is_byte<Tsrc>::value);
|
static_assert(std::is_integral<Tsrc>::value || mpt::is_byte<Tsrc>::value);
|
||||||
STATIC_ASSERT(std::is_integral<Tdst>::value || mpt::is_byte<Tdst>::value);
|
static_assert(std::is_integral<Tdst>::value || mpt::is_byte<Tdst>::value);
|
||||||
return static_cast<Tdst>(src);
|
return static_cast<Tdst>(src);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -209,13 +173,13 @@ struct byte_cast_impl<mpt::span<Tdst>, mpt::span<Tsrc> >
|
||||||
{
|
{
|
||||||
inline mpt::span<Tdst> operator () (mpt::span<Tsrc> src) const
|
inline mpt::span<Tdst> operator () (mpt::span<Tsrc> src) const
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(sizeof(Tsrc) == sizeof(mpt::byte));
|
static_assert(sizeof(Tsrc) == sizeof(std::byte));
|
||||||
STATIC_ASSERT(sizeof(Tdst) == sizeof(mpt::byte));
|
static_assert(sizeof(Tdst) == sizeof(std::byte));
|
||||||
STATIC_ASSERT(mpt::is_byte_castable<Tsrc>::value);
|
static_assert(mpt::is_byte_castable<Tsrc>::value);
|
||||||
STATIC_ASSERT(mpt::is_byte_castable<Tdst>::value);
|
static_assert(mpt::is_byte_castable<Tdst>::value);
|
||||||
STATIC_ASSERT(std::is_integral<Tsrc>::value || mpt::is_byte<Tsrc>::value);
|
static_assert(std::is_integral<Tsrc>::value || mpt::is_byte<Tsrc>::value);
|
||||||
STATIC_ASSERT(std::is_integral<Tdst>::value || mpt::is_byte<Tdst>::value);
|
static_assert(std::is_integral<Tdst>::value || mpt::is_byte<Tdst>::value);
|
||||||
return mpt::as_span(mpt::byte_cast_impl<Tdst*, Tsrc*>()(src.begin()), mpt::byte_cast_impl<Tdst*, Tsrc*>()(src.end()));
|
return mpt::as_span(mpt::byte_cast_impl<Tdst*, Tsrc*>()(src.data()), mpt::byte_cast_impl<Tdst*, Tsrc*>()(src.data() + src.size()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
template <typename Tdst, typename Tsrc>
|
template <typename Tdst, typename Tsrc>
|
||||||
|
@ -223,12 +187,12 @@ struct byte_cast_impl<Tdst*, Tsrc*>
|
||||||
{
|
{
|
||||||
inline Tdst* operator () (Tsrc* src) const
|
inline Tdst* operator () (Tsrc* src) const
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(sizeof(Tsrc) == sizeof(mpt::byte));
|
static_assert(sizeof(Tsrc) == sizeof(std::byte));
|
||||||
STATIC_ASSERT(sizeof(Tdst) == sizeof(mpt::byte));
|
static_assert(sizeof(Tdst) == sizeof(std::byte));
|
||||||
STATIC_ASSERT(mpt::is_byte_castable<Tsrc>::value);
|
static_assert(mpt::is_byte_castable<Tsrc>::value);
|
||||||
STATIC_ASSERT(mpt::is_byte_castable<Tdst>::value);
|
static_assert(mpt::is_byte_castable<Tdst>::value);
|
||||||
STATIC_ASSERT(std::is_integral<Tsrc>::value || mpt::is_byte<Tsrc>::value);
|
static_assert(std::is_integral<Tsrc>::value || mpt::is_byte<Tsrc>::value);
|
||||||
STATIC_ASSERT(std::is_integral<Tdst>::value || mpt::is_byte<Tdst>::value);
|
static_assert(std::is_integral<Tdst>::value || mpt::is_byte<Tdst>::value);
|
||||||
return reinterpret_cast<Tdst*>(src);
|
return reinterpret_cast<Tdst*>(src);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -241,9 +205,9 @@ struct void_cast_impl<Tdst*, void*>
|
||||||
{
|
{
|
||||||
inline Tdst* operator () (void* src) const
|
inline Tdst* operator () (void* src) const
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(sizeof(Tdst) == sizeof(mpt::byte));
|
static_assert(sizeof(Tdst) == sizeof(std::byte));
|
||||||
STATIC_ASSERT(mpt::is_byte_castable<Tdst>::value);
|
static_assert(mpt::is_byte_castable<Tdst>::value);
|
||||||
STATIC_ASSERT(std::is_integral<Tdst>::value || mpt::is_byte<Tdst>::value);
|
static_assert(std::is_integral<Tdst>::value || mpt::is_byte<Tdst>::value);
|
||||||
return reinterpret_cast<Tdst*>(src);
|
return reinterpret_cast<Tdst*>(src);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -252,9 +216,9 @@ struct void_cast_impl<Tdst*, const void*>
|
||||||
{
|
{
|
||||||
inline Tdst* operator () (const void* src) const
|
inline Tdst* operator () (const void* src) const
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(sizeof(Tdst) == sizeof(mpt::byte));
|
static_assert(sizeof(Tdst) == sizeof(std::byte));
|
||||||
STATIC_ASSERT(mpt::is_byte_castable<Tdst>::value);
|
static_assert(mpt::is_byte_castable<Tdst>::value);
|
||||||
STATIC_ASSERT(std::is_integral<Tdst>::value || mpt::is_byte<Tdst>::value);
|
static_assert(std::is_integral<Tdst>::value || mpt::is_byte<Tdst>::value);
|
||||||
return reinterpret_cast<Tdst*>(src);
|
return reinterpret_cast<Tdst*>(src);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -263,9 +227,9 @@ struct void_cast_impl<void*, Tsrc*>
|
||||||
{
|
{
|
||||||
inline void* operator () (Tsrc* src) const
|
inline void* operator () (Tsrc* src) const
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(sizeof(Tsrc) == sizeof(mpt::byte));
|
static_assert(sizeof(Tsrc) == sizeof(std::byte));
|
||||||
STATIC_ASSERT(mpt::is_byte_castable<Tsrc>::value);
|
static_assert(mpt::is_byte_castable<Tsrc>::value);
|
||||||
STATIC_ASSERT(std::is_integral<Tsrc>::value || mpt::is_byte<Tsrc>::value);
|
static_assert(std::is_integral<Tsrc>::value || mpt::is_byte<Tsrc>::value);
|
||||||
return reinterpret_cast<void*>(src);
|
return reinterpret_cast<void*>(src);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -274,9 +238,9 @@ struct void_cast_impl<const void*, Tsrc*>
|
||||||
{
|
{
|
||||||
inline const void* operator () (Tsrc* src) const
|
inline const void* operator () (Tsrc* src) const
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(sizeof(Tsrc) == sizeof(mpt::byte));
|
static_assert(sizeof(Tsrc) == sizeof(std::byte));
|
||||||
STATIC_ASSERT(mpt::is_byte_castable<Tsrc>::value);
|
static_assert(mpt::is_byte_castable<Tsrc>::value);
|
||||||
STATIC_ASSERT(std::is_integral<Tsrc>::value || mpt::is_byte<Tsrc>::value);
|
static_assert(std::is_integral<Tsrc>::value || mpt::is_byte<Tsrc>::value);
|
||||||
return reinterpret_cast<const void*>(src);
|
return reinterpret_cast<const void*>(src);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -298,10 +262,10 @@ inline Tdst void_cast(Tsrc src)
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
MPT_CONSTEXPR14_FUN mpt::byte as_byte(T src) noexcept
|
MPT_CONSTEXPR14_FUN std::byte as_byte(T src) noexcept
|
||||||
{
|
{
|
||||||
MPT_STATIC_ASSERT(std::is_integral<T>::value);
|
static_assert(std::is_integral<T>::value);
|
||||||
return static_cast<mpt::byte>(static_cast<uint8>(src));
|
return static_cast<std::byte>(static_cast<uint8>(src));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -311,13 +275,13 @@ struct GetRawBytesFunctor
|
||||||
{
|
{
|
||||||
inline mpt::const_byte_span operator () (const T & v) const
|
inline mpt::const_byte_span operator () (const T & v) const
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(mpt::is_binary_safe<typename std::remove_const<T>::type>::value);
|
static_assert(mpt::is_binary_safe<typename std::remove_const<T>::type>::value);
|
||||||
return mpt::as_span(reinterpret_cast<const mpt::byte *>(&v), sizeof(T));
|
return mpt::as_span(reinterpret_cast<const std::byte *>(&v), sizeof(T));
|
||||||
}
|
}
|
||||||
inline mpt::byte_span operator () (T & v) const
|
inline mpt::byte_span operator () (T & v) const
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(mpt::is_binary_safe<typename std::remove_const<T>::type>::value);
|
static_assert(mpt::is_binary_safe<typename std::remove_const<T>::type>::value);
|
||||||
return mpt::as_span(reinterpret_cast<mpt::byte *>(&v), sizeof(T));
|
return mpt::as_span(reinterpret_cast<std::byte *>(&v), sizeof(T));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -326,13 +290,13 @@ struct GetRawBytesFunctor<T[N]>
|
||||||
{
|
{
|
||||||
inline mpt::const_byte_span operator () (const T (&v)[N]) const
|
inline mpt::const_byte_span operator () (const T (&v)[N]) const
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(mpt::is_binary_safe<typename std::remove_const<T>::type>::value);
|
static_assert(mpt::is_binary_safe<typename std::remove_const<T>::type>::value);
|
||||||
return mpt::as_span(reinterpret_cast<const mpt::byte *>(v), N * sizeof(T));
|
return mpt::as_span(reinterpret_cast<const std::byte *>(v), N * sizeof(T));
|
||||||
}
|
}
|
||||||
inline mpt::byte_span operator () (T (&v)[N]) const
|
inline mpt::byte_span operator () (T (&v)[N]) const
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(mpt::is_binary_safe<typename std::remove_const<T>::type>::value);
|
static_assert(mpt::is_binary_safe<typename std::remove_const<T>::type>::value);
|
||||||
return mpt::as_span(reinterpret_cast<mpt::byte *>(v), N * sizeof(T));
|
return mpt::as_span(reinterpret_cast<std::byte *>(v), N * sizeof(T));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -341,15 +305,15 @@ struct GetRawBytesFunctor<const T[N]>
|
||||||
{
|
{
|
||||||
inline mpt::const_byte_span operator () (const T (&v)[N]) const
|
inline mpt::const_byte_span operator () (const T (&v)[N]) const
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(mpt::is_binary_safe<typename std::remove_const<T>::type>::value);
|
static_assert(mpt::is_binary_safe<typename std::remove_const<T>::type>::value);
|
||||||
return mpt::as_span(reinterpret_cast<const mpt::byte *>(v), N * sizeof(T));
|
return mpt::as_span(reinterpret_cast<const std::byte *>(v), N * sizeof(T));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// In order to be able to partially specialize it,
|
// In order to be able to partially specialize it,
|
||||||
// as_raw_memory is implemented via a class template.
|
// as_raw_memory is implemented via a class template.
|
||||||
// Do not overload or specialize as_raw_memory directly.
|
// Do not overload or specialize as_raw_memory directly.
|
||||||
// Using a wrapper (by default just around a cast to const mpt::byte *),
|
// Using a wrapper (by default just around a cast to const std::byte *),
|
||||||
// allows for implementing raw memory access
|
// allows for implementing raw memory access
|
||||||
// via on-demand generating a cached serialized representation.
|
// via on-demand generating a cached serialized representation.
|
||||||
template <typename T> inline mpt::const_byte_span as_raw_memory(const T & v)
|
template <typename T> inline mpt::const_byte_span as_raw_memory(const T & v)
|
||||||
|
|
|
@ -174,7 +174,7 @@ public:
|
||||||
|
|
||||||
#if MPT_MUTEX_STD
|
#if MPT_MUTEX_STD
|
||||||
|
|
||||||
#define MPT_LOCK_GUARD std::lock_guard
|
template <typename T> using lock_guard = std::lock_guard<T>;
|
||||||
|
|
||||||
#else // !MPT_MUTEX_STD
|
#else // !MPT_MUTEX_STD
|
||||||
|
|
||||||
|
@ -188,8 +188,6 @@ public:
|
||||||
~lock_guard() { mutex.unlock(); }
|
~lock_guard() { mutex.unlock(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MPT_LOCK_GUARD mpt::lock_guard
|
|
||||||
|
|
||||||
#endif // MPT_MUTEX_STD
|
#endif // MPT_MUTEX_STD
|
||||||
|
|
||||||
#ifdef MODPLUG_TRACKER
|
#ifdef MODPLUG_TRACKER
|
||||||
|
|
|
@ -15,10 +15,71 @@
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(MODPLUG_TRACKER)
|
||||||
|
#if !MPT_OS_WINDOWS
|
||||||
|
#include <sys/utsname.h>
|
||||||
|
#endif // !MPT_OS_WINDOWS
|
||||||
|
#endif // MODPLUG_TRACKER
|
||||||
|
|
||||||
|
|
||||||
OPENMPT_NAMESPACE_BEGIN
|
OPENMPT_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(MODPLUG_TRACKER)
|
||||||
|
|
||||||
|
namespace mpt
|
||||||
|
{
|
||||||
|
namespace OS
|
||||||
|
{
|
||||||
|
|
||||||
|
mpt::OS::Class GetClassFromSysname(mpt::ustring sysname)
|
||||||
|
{
|
||||||
|
mpt::OS::Class result = mpt::OS::Class::Unknown;
|
||||||
|
if(sysname == U_(""))
|
||||||
|
{
|
||||||
|
result = mpt::OS::Class::Unknown;
|
||||||
|
} else if(sysname == U_("Windows") || sysname == U_("WindowsNT") || sysname == U_("Windows_NT"))
|
||||||
|
{
|
||||||
|
result = mpt::OS::Class::Windows;
|
||||||
|
} else if(sysname == U_("Linux"))
|
||||||
|
{
|
||||||
|
result = mpt::OS::Class::Linux;
|
||||||
|
} else if(sysname == U_("Darwin"))
|
||||||
|
{
|
||||||
|
result = mpt::OS::Class::Darwin;
|
||||||
|
} else if(sysname == U_("FreeBSD") || sysname == U_("DragonFly") || sysname == U_("NetBSD") || sysname == U_("OpenBSD") || sysname == U_("MidnightBSD"))
|
||||||
|
{
|
||||||
|
result = mpt::OS::Class::BSD;
|
||||||
|
} else if(sysname == U_("Haiku"))
|
||||||
|
{
|
||||||
|
result = mpt::OS::Class::Haiku;
|
||||||
|
} else if(sysname == U_("MS-DOS"))
|
||||||
|
{
|
||||||
|
result = mpt::OS::Class::DOS;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
mpt::OS::Class GetClass()
|
||||||
|
{
|
||||||
|
#if MPT_OS_WINDOWS
|
||||||
|
return mpt::OS::Class::Windows;
|
||||||
|
#else // !MPT_OS_WINDOWS
|
||||||
|
utsname uname_result;
|
||||||
|
if(uname(&uname_result) != 0)
|
||||||
|
{
|
||||||
|
return mpt::OS::Class::Unknown;
|
||||||
|
}
|
||||||
|
return mpt::OS::GetClassFromSysname(mpt::ToUnicode(mpt::Charset::ASCII, mpt::String::ReadAutoBuf(uname_result.sysname)));
|
||||||
|
#endif // MPT_OS_WINDOWS
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace OS
|
||||||
|
} // namespace mpt
|
||||||
|
|
||||||
|
#endif // MODPLUG_TRACKER
|
||||||
|
|
||||||
|
|
||||||
namespace mpt
|
namespace mpt
|
||||||
{
|
{
|
||||||
namespace Windows
|
namespace Windows
|
||||||
|
@ -52,7 +113,7 @@ static mpt::Windows::Version VersionFromNTDDI_VERSION() noexcept
|
||||||
mpt::Windows::Version::WinNT4
|
mpt::Windows::Version::WinNT4
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
return mpt::Windows::Version(System, mpt::Windows::Version::ServicePack(((NTDDI_VERSION & 0xffffu) >> 8) & 0xffu, ((NTDDI_VERSION & 0xffffu) >> 0) & 0xffu), 0);
|
return mpt::Windows::Version(System, mpt::Windows::Version::ServicePack(((NTDDI_VERSION & 0xffffu) >> 8) & 0xffu, ((NTDDI_VERSION & 0xffffu) >> 0) & 0xffu), 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -77,6 +138,7 @@ static mpt::Windows::Version GatherWindowsVersion() noexcept
|
||||||
#if MPT_COMPILER_MSVC
|
#if MPT_COMPILER_MSVC
|
||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
#pragma warning(disable:4996) // 'GetVersionExW': was declared deprecated
|
#pragma warning(disable:4996) // 'GetVersionExW': was declared deprecated
|
||||||
|
#pragma warning(disable:28159) // Consider using 'IsWindows*' instead of 'GetVersionExW'. Reason: Deprecated. Use VerifyVersionInfo* or IsWindows* macros from VersionHelpers.
|
||||||
#endif // MPT_COMPILER_MSVC
|
#endif // MPT_COMPILER_MSVC
|
||||||
#if MPT_COMPILER_CLANG
|
#if MPT_COMPILER_CLANG
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
|
@ -96,10 +158,17 @@ static mpt::Windows::Version GatherWindowsVersion() noexcept
|
||||||
{
|
{
|
||||||
return VersionFromNTDDI_VERSION();
|
return VersionFromNTDDI_VERSION();
|
||||||
}
|
}
|
||||||
|
DWORD dwProductType = 0;
|
||||||
|
dwProductType = PRODUCT_UNDEFINED;
|
||||||
|
if(GetProductInfo(versioninfoex.dwMajorVersion, versioninfoex.dwMinorVersion, versioninfoex.wServicePackMajor, versioninfoex.wServicePackMinor, &dwProductType) == FALSE)
|
||||||
|
{
|
||||||
|
dwProductType = PRODUCT_UNDEFINED;
|
||||||
|
}
|
||||||
return mpt::Windows::Version(
|
return mpt::Windows::Version(
|
||||||
mpt::Windows::Version::System(versioninfoex.dwMajorVersion, versioninfoex.dwMinorVersion),
|
mpt::Windows::Version::System(versioninfoex.dwMajorVersion, versioninfoex.dwMinorVersion),
|
||||||
mpt::Windows::Version::ServicePack(versioninfoex.wServicePackMajor, versioninfoex.wServicePackMinor),
|
mpt::Windows::Version::ServicePack(versioninfoex.wServicePackMajor, versioninfoex.wServicePackMinor),
|
||||||
versioninfoex.dwBuildNumber
|
versioninfoex.dwBuildNumber,
|
||||||
|
dwProductType
|
||||||
);
|
);
|
||||||
#endif // MPT_OS_WINDOWS_WINRT
|
#endif // MPT_OS_WINDOWS_WINRT
|
||||||
}
|
}
|
||||||
|
@ -135,6 +204,7 @@ Version::Version() noexcept
|
||||||
, m_System()
|
, m_System()
|
||||||
, m_ServicePack()
|
, m_ServicePack()
|
||||||
, m_Build()
|
, m_Build()
|
||||||
|
, m_Type()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,11 +215,12 @@ Version Version::NoWindows() noexcept
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Version::Version(mpt::Windows::Version::System system, mpt::Windows::Version::ServicePack servicePack, mpt::Windows::Version::Build build) noexcept
|
Version::Version(mpt::Windows::Version::System system, mpt::Windows::Version::ServicePack servicePack, mpt::Windows::Version::Build build, mpt::Windows::Version::TypeId type) noexcept
|
||||||
: m_SystemIsWindows(true)
|
: m_SystemIsWindows(true)
|
||||||
, m_System(system)
|
, m_System(system)
|
||||||
, m_ServicePack(servicePack)
|
, m_ServicePack(servicePack)
|
||||||
, m_Build(build)
|
, m_Build(build)
|
||||||
|
, m_Type(type)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,7 +355,13 @@ mpt::Windows::Version::Build Version::GetBuild() const noexcept
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static MPT_CONSTEXPR11_VAR struct { Version::System version; const MPT_UCHAR_TYPE * name; bool showDetails; } versionMap[] =
|
mpt::Windows::Version::TypeId Version::GetTypeId() const noexcept
|
||||||
|
{
|
||||||
|
return m_Type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static constexpr struct { Version::System version; const mpt::uchar * name; bool showDetails; } versionMap[] =
|
||||||
{
|
{
|
||||||
{ mpt::Windows::Version::WinNewer, UL_("Windows 10 (or newer)"), false },
|
{ mpt::Windows::Version::WinNewer, UL_("Windows 10 (or newer)"), false },
|
||||||
{ mpt::Windows::Version::Win10, UL_("Windows 10"), true },
|
{ mpt::Windows::Version::Win10, UL_("Windows 10"), true },
|
||||||
|
@ -369,7 +446,7 @@ mpt::ustring Version::GetName() const
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
result = mpt::format(U_("Wine (unknown version: '%1') (%2)"))(
|
result = mpt::format(U_("Wine (unknown version: '%1') (%2)"))(
|
||||||
mpt::ToUnicode(mpt::CharsetUTF8, v.RawVersion())
|
mpt::ToUnicode(mpt::Charset::UTF8, v.RawVersion())
|
||||||
, name
|
, name
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -410,11 +487,7 @@ mpt::Windows::Version::System Version::GetMinimumKernelLevel() noexcept
|
||||||
{
|
{
|
||||||
uint64 minimumKernelVersion = 0;
|
uint64 minimumKernelVersion = 0;
|
||||||
#if MPT_OS_WINDOWS && MPT_COMPILER_MSVC
|
#if MPT_OS_WINDOWS && MPT_COMPILER_MSVC
|
||||||
#if !defined(MPT_BUILD_TARGET_XP)
|
minimumKernelVersion = std::max(minimumKernelVersion, static_cast<uint64>(mpt::Windows::Version::WinVista));
|
||||||
minimumKernelVersion = std::max<uint64>(minimumKernelVersion, mpt::Windows::Version::WinVista);
|
|
||||||
#else
|
|
||||||
minimumKernelVersion = std::max<uint64>(minimumKernelVersion, mpt::Windows::Version::WinXP);
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
return mpt::Windows::Version::System(minimumKernelVersion);
|
return mpt::Windows::Version::System(minimumKernelVersion);
|
||||||
}
|
}
|
||||||
|
@ -502,7 +575,7 @@ struct ArchitectureInfo
|
||||||
{
|
{
|
||||||
Architecture Arch;
|
Architecture Arch;
|
||||||
int Bitness;
|
int Bitness;
|
||||||
const MPT_UCHAR_TYPE * Name;
|
const mpt::uchar * Name;
|
||||||
};
|
};
|
||||||
static constexpr ArchitectureInfo architectureInfo [] = {
|
static constexpr ArchitectureInfo architectureInfo [] = {
|
||||||
{ Architecture::x86 , 32, UL_("x86") },
|
{ Architecture::x86 , 32, UL_("x86") },
|
||||||
|
@ -836,8 +909,7 @@ mpt::Wine::Version GetMinimumWineVersion()
|
||||||
|
|
||||||
VersionContext::VersionContext()
|
VersionContext::VersionContext()
|
||||||
: m_IsWine(false)
|
: m_IsWine(false)
|
||||||
, m_HostIsLinux(false)
|
, m_HostClass(mpt::OS::Class::Unknown)
|
||||||
, m_HostIsBSD(false)
|
|
||||||
{
|
{
|
||||||
#if MPT_OS_WINDOWS
|
#if MPT_OS_WINDOWS
|
||||||
m_IsWine = mpt::Windows::IsWine();
|
m_IsWine = mpt::Windows::IsWine();
|
||||||
|
@ -869,9 +941,8 @@ VersionContext::VersionContext()
|
||||||
m_RawHostSysName = wine_host_sysname ? wine_host_sysname : "";
|
m_RawHostSysName = wine_host_sysname ? wine_host_sysname : "";
|
||||||
m_RawHostRelease = wine_host_release ? wine_host_release : "";
|
m_RawHostRelease = wine_host_release ? wine_host_release : "";
|
||||||
}
|
}
|
||||||
m_Version = mpt::Wine::Version(mpt::ToUnicode(mpt::CharsetUTF8, m_RawVersion));
|
m_Version = mpt::Wine::Version(mpt::ToUnicode(mpt::Charset::UTF8, m_RawVersion));
|
||||||
m_HostIsLinux = (m_RawHostSysName == "Linux");
|
m_HostClass = mpt::OS::GetClassFromSysname(mpt::ToUnicode(mpt::Charset::UTF8, m_RawHostSysName));
|
||||||
m_HostIsBSD = (m_RawHostSysName == "FreeBSD" || m_RawHostSysName == "DragonFly" || m_RawHostSysName == "NetBSD" || m_RawHostSysName == "OpenBSD");
|
|
||||||
#endif // MPT_OS_WINDOWS
|
#endif // MPT_OS_WINDOWS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,34 @@
|
||||||
OPENMPT_NAMESPACE_BEGIN
|
OPENMPT_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(MODPLUG_TRACKER)
|
||||||
|
|
||||||
|
namespace mpt
|
||||||
|
{
|
||||||
|
namespace OS
|
||||||
|
{
|
||||||
|
|
||||||
|
enum class Class
|
||||||
|
{
|
||||||
|
Unknown,
|
||||||
|
Windows,
|
||||||
|
Linux,
|
||||||
|
Darwin,
|
||||||
|
BSD,
|
||||||
|
Haiku,
|
||||||
|
DOS,
|
||||||
|
};
|
||||||
|
|
||||||
|
mpt::OS::Class GetClassFromSysname(mpt::ustring sysname);
|
||||||
|
|
||||||
|
mpt::OS::Class GetClass();
|
||||||
|
|
||||||
|
} // namespace OS
|
||||||
|
} // namespace mpt
|
||||||
|
|
||||||
|
#endif // MODPLUG_TRACKER
|
||||||
|
|
||||||
|
|
||||||
namespace mpt
|
namespace mpt
|
||||||
{
|
{
|
||||||
namespace Windows
|
namespace Windows
|
||||||
|
@ -92,6 +120,8 @@ public:
|
||||||
|
|
||||||
typedef uint32 Build;
|
typedef uint32 Build;
|
||||||
|
|
||||||
|
typedef uint32 TypeId;
|
||||||
|
|
||||||
static mpt::ustring VersionToString(mpt::Windows::Version::System version);
|
static mpt::ustring VersionToString(mpt::Windows::Version::System version);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -101,6 +131,7 @@ private:
|
||||||
System m_System;
|
System m_System;
|
||||||
ServicePack m_ServicePack;
|
ServicePack m_ServicePack;
|
||||||
Build m_Build;
|
Build m_Build;
|
||||||
|
TypeId m_Type;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -110,7 +141,7 @@ public:
|
||||||
|
|
||||||
static Version NoWindows() noexcept;
|
static Version NoWindows() noexcept;
|
||||||
|
|
||||||
Version(mpt::Windows::Version::System system, mpt::Windows::Version::ServicePack servicePack, mpt::Windows::Version::Build build) noexcept;
|
Version(mpt::Windows::Version::System system, mpt::Windows::Version::ServicePack servicePack, mpt::Windows::Version::Build build, mpt::Windows::Version::TypeId type) noexcept;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -131,6 +162,7 @@ public:
|
||||||
mpt::Windows::Version::System GetSystem() const noexcept;
|
mpt::Windows::Version::System GetSystem() const noexcept;
|
||||||
mpt::Windows::Version::ServicePack GetServicePack() const noexcept;
|
mpt::Windows::Version::ServicePack GetServicePack() const noexcept;
|
||||||
mpt::Windows::Version::Build GetBuild() const noexcept;
|
mpt::Windows::Version::Build GetBuild() const noexcept;
|
||||||
|
mpt::Windows::Version::TypeId GetTypeId() const noexcept;
|
||||||
|
|
||||||
mpt::ustring GetName() const;
|
mpt::ustring GetName() const;
|
||||||
#ifdef MODPLUG_TRACKER
|
#ifdef MODPLUG_TRACKER
|
||||||
|
@ -248,8 +280,7 @@ protected:
|
||||||
std::string m_RawHostSysName;
|
std::string m_RawHostSysName;
|
||||||
std::string m_RawHostRelease;
|
std::string m_RawHostRelease;
|
||||||
mpt::Wine::Version m_Version;
|
mpt::Wine::Version m_Version;
|
||||||
bool m_HostIsLinux;
|
mpt::OS::Class m_HostClass;
|
||||||
bool m_HostIsBSD;
|
|
||||||
public:
|
public:
|
||||||
VersionContext();
|
VersionContext();
|
||||||
public:
|
public:
|
||||||
|
@ -260,8 +291,7 @@ public:
|
||||||
std::string RawHostSysName() const { return m_RawHostSysName; }
|
std::string RawHostSysName() const { return m_RawHostSysName; }
|
||||||
std::string RawHostRelease() const { return m_RawHostRelease; }
|
std::string RawHostRelease() const { return m_RawHostRelease; }
|
||||||
mpt::Wine::Version Version() const { return m_Version; }
|
mpt::Wine::Version Version() const { return m_Version; }
|
||||||
bool HostIsLinux() const { return m_HostIsLinux; }
|
mpt::OS::Class HostClass() const { return m_HostClass; }
|
||||||
bool HostIsBSD() const { return m_HostIsBSD; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Wine
|
} // namespace Wine
|
||||||
|
|
99
Frameworks/OpenMPT/OpenMPT/common/mptOSError.h
Normal file
99
Frameworks/OpenMPT/OpenMPT/common/mptOSError.h
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
/*
|
||||||
|
* mptOSError.h
|
||||||
|
* ------------
|
||||||
|
* Purpose: OS-specific error message handling.
|
||||||
|
* Notes : (currently none)
|
||||||
|
* Authors: OpenMPT Devs
|
||||||
|
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "BuildSettings.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "mptBaseMacros.h"
|
||||||
|
#include "mptException.h"
|
||||||
|
#include "mptString.h"
|
||||||
|
#include "mptStringFormat.h"
|
||||||
|
|
||||||
|
#if defined(MODPLUG_TRACKER)
|
||||||
|
#if MPT_OS_WINDOWS
|
||||||
|
#include <stdexcept>
|
||||||
|
#endif // MPT_OS_WINDOWS
|
||||||
|
#endif // MODPLUG_TRACKER
|
||||||
|
|
||||||
|
#if defined(MODPLUG_TRACKER)
|
||||||
|
#if MPT_OS_WINDOWS
|
||||||
|
#include <windows.h>
|
||||||
|
#endif // MPT_OS_WINDOWS
|
||||||
|
#endif // MODPLUG_TRACKER
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
OPENMPT_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(MODPLUG_TRACKER)
|
||||||
|
#if MPT_OS_WINDOWS
|
||||||
|
|
||||||
|
namespace Windows
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
inline mpt::ustring GetErrorMessage(DWORD errorCode, HANDLE hModule = NULL)
|
||||||
|
{
|
||||||
|
mpt::ustring message;
|
||||||
|
void *lpMsgBuf = nullptr;
|
||||||
|
FormatMessage(
|
||||||
|
FORMAT_MESSAGE_ALLOCATE_BUFFER | (hModule ? FORMAT_MESSAGE_FROM_HMODULE : 0) | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
|
hModule,
|
||||||
|
errorCode,
|
||||||
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
|
(LPTSTR)&lpMsgBuf,
|
||||||
|
0,
|
||||||
|
NULL);
|
||||||
|
if(!lpMsgBuf)
|
||||||
|
{
|
||||||
|
DWORD e = GetLastError();
|
||||||
|
if((e == ERROR_NOT_ENOUGH_MEMORY) || (e == ERROR_OUTOFMEMORY))
|
||||||
|
{
|
||||||
|
MPT_EXCEPTION_THROW_OUT_OF_MEMORY();
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
message = mpt::ToUnicode(mpt::winstring((LPTSTR)lpMsgBuf));
|
||||||
|
} MPT_EXCEPTION_CATCH_OUT_OF_MEMORY(e)
|
||||||
|
{
|
||||||
|
LocalFree(lpMsgBuf);
|
||||||
|
MPT_EXCEPTION_RETHROW_OUT_OF_MEMORY(e);
|
||||||
|
}
|
||||||
|
LocalFree(lpMsgBuf);
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Error
|
||||||
|
: public std::runtime_error
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Error(DWORD errorCode, HANDLE hModule = NULL)
|
||||||
|
: std::runtime_error(mpt::ToCharset(mpt::CharsetException, mpt::format(U_("Windows Error: 0x%1: %2"))(mpt::ufmt::hex0<8>(errorCode), GetErrorMessage(errorCode, hModule))))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace Windows
|
||||||
|
|
||||||
|
#endif // MPT_OS_WINDOWS
|
||||||
|
#endif // MODPLUG_TRACKER
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
OPENMPT_NAMESPACE_END
|
188
Frameworks/OpenMPT/OpenMPT/common/mptOSException.h
Normal file
188
Frameworks/OpenMPT/OpenMPT/common/mptOSException.h
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
/*
|
||||||
|
* mptOSException.h
|
||||||
|
* ----------------
|
||||||
|
* Purpose: platform-specific exception/signal handling
|
||||||
|
* Notes : (currently none)
|
||||||
|
* Authors: OpenMPT Devs
|
||||||
|
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "BuildSettings.h"
|
||||||
|
|
||||||
|
#include "mptBaseMacros.h"
|
||||||
|
#include "mptBaseTypes.h"
|
||||||
|
|
||||||
|
#if defined(MODPLUG_TRACKER)
|
||||||
|
#if MPT_OS_WINDOWS
|
||||||
|
#include <windows.h>
|
||||||
|
#endif // MPT_OS_WINDOWS
|
||||||
|
#endif // MODPLUG_TRACKER
|
||||||
|
|
||||||
|
|
||||||
|
OPENMPT_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(MODPLUG_TRACKER)
|
||||||
|
|
||||||
|
|
||||||
|
#if MPT_OS_WINDOWS
|
||||||
|
|
||||||
|
|
||||||
|
namespace Windows
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
namespace SEH
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
struct Code
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
DWORD m_Code;
|
||||||
|
public:
|
||||||
|
constexpr Code(DWORD code) noexcept
|
||||||
|
: m_Code(code)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
constexpr DWORD code() const noexcept
|
||||||
|
{
|
||||||
|
return m_Code;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename Tfn, typename Tfilter, typename Thandler>
|
||||||
|
auto TryFilterHandleThrow(const Tfn &fn, const Tfilter &filter, const Thandler &handler) -> decltype(fn())
|
||||||
|
{
|
||||||
|
static_assert(std::is_trivially_copy_assignable<decltype(fn())>::value);
|
||||||
|
static_assert(std::is_trivially_copy_constructible<decltype(fn())>::value);
|
||||||
|
static_assert(std::is_trivially_move_assignable<decltype(fn())>::value);
|
||||||
|
static_assert(std::is_trivially_move_constructible<decltype(fn())>::value);
|
||||||
|
DWORD code = 0;
|
||||||
|
__try
|
||||||
|
{
|
||||||
|
return fn();
|
||||||
|
} __except(filter(GetExceptionCode(), GetExceptionInformation()))
|
||||||
|
{
|
||||||
|
code = GetExceptionCode();
|
||||||
|
}
|
||||||
|
throw Windows::SEH::Code(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename Tfn, typename Tfilter, typename Thandler>
|
||||||
|
void TryFilterHandleVoid(const Tfn &fn, const Tfilter &filter, const Thandler &handler)
|
||||||
|
{
|
||||||
|
static_assert(std::is_same<decltype(fn()), void>::value || std::is_trivially_copy_assignable<decltype(fn())>::value);
|
||||||
|
static_assert(std::is_same<decltype(fn()), void>::value || std::is_trivially_copy_constructible<decltype(fn())>::value);
|
||||||
|
static_assert(std::is_same<decltype(fn()), void>::value || std::is_trivially_move_assignable<decltype(fn())>::value);
|
||||||
|
static_assert(std::is_same<decltype(fn()), void>::value || std::is_trivially_move_constructible<decltype(fn())>::value);
|
||||||
|
__try
|
||||||
|
{
|
||||||
|
fn();
|
||||||
|
return;
|
||||||
|
} __except(filter(GetExceptionCode(), GetExceptionInformation()))
|
||||||
|
{
|
||||||
|
DWORD code = GetExceptionCode();
|
||||||
|
handler(code);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename Tfn, typename Tfilter, typename Thandler>
|
||||||
|
auto TryFilterHandleDefault(const Tfn &fn, const Tfilter &filter, const Thandler &handler, decltype(fn()) def = decltype(fn()){}) -> decltype(fn())
|
||||||
|
{
|
||||||
|
static_assert(std::is_trivially_copy_assignable<decltype(fn())>::value);
|
||||||
|
static_assert(std::is_trivially_copy_constructible<decltype(fn())>::value);
|
||||||
|
static_assert(std::is_trivially_move_assignable<decltype(fn())>::value);
|
||||||
|
static_assert(std::is_trivially_move_constructible<decltype(fn())>::value);
|
||||||
|
auto result = def;
|
||||||
|
__try
|
||||||
|
{
|
||||||
|
result = fn();
|
||||||
|
} __except(filter(GetExceptionCode(), GetExceptionInformation()))
|
||||||
|
{
|
||||||
|
DWORD code = GetExceptionCode();
|
||||||
|
result = handler(code);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename Tfn>
|
||||||
|
auto TryReturnOrThrow(const Tfn &fn) -> decltype(fn())
|
||||||
|
{
|
||||||
|
return TryFilterHandleThrow(
|
||||||
|
fn,
|
||||||
|
[](auto code, auto eptr)
|
||||||
|
{
|
||||||
|
MPT_UNREFERENCED_PARAMETER(code);
|
||||||
|
MPT_UNREFERENCED_PARAMETER(eptr);
|
||||||
|
return EXCEPTION_EXECUTE_HANDLER;
|
||||||
|
},
|
||||||
|
[](auto code)
|
||||||
|
{
|
||||||
|
throw Windows::SEH::Code(code);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename Tfn>
|
||||||
|
DWORD TryOrError(const Tfn &fn)
|
||||||
|
{
|
||||||
|
DWORD result = DWORD{0};
|
||||||
|
TryFilterHandleVoid(
|
||||||
|
fn,
|
||||||
|
[](auto code, auto eptr)
|
||||||
|
{
|
||||||
|
MPT_UNREFERENCED_PARAMETER(code);
|
||||||
|
MPT_UNREFERENCED_PARAMETER(eptr);
|
||||||
|
return EXCEPTION_EXECUTE_HANDLER;
|
||||||
|
},
|
||||||
|
[&result](auto code)
|
||||||
|
{
|
||||||
|
result = code;
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename Tfn>
|
||||||
|
auto TryReturnOrDefault(const Tfn &fn, decltype(fn()) def = decltype(fn()){}) -> decltype(fn())
|
||||||
|
{
|
||||||
|
return TryFilterHandleDefault(
|
||||||
|
fn,
|
||||||
|
[](auto code, auto eptr)
|
||||||
|
{
|
||||||
|
MPT_UNREFERENCED_PARAMETER(code);
|
||||||
|
MPT_UNREFERENCED_PARAMETER(eptr);
|
||||||
|
return EXCEPTION_EXECUTE_HANDLER;
|
||||||
|
},
|
||||||
|
[def](auto code)
|
||||||
|
{
|
||||||
|
MPT_UNREFERENCED_PARAMETER(code);
|
||||||
|
return def;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namspace SEH
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace Windows
|
||||||
|
|
||||||
|
|
||||||
|
#endif // MPT_OS_WINDOWS
|
||||||
|
|
||||||
|
|
||||||
|
#endif // MODPLUG_TRACKER
|
||||||
|
|
||||||
|
|
||||||
|
OPENMPT_NAMESPACE_END
|
|
@ -524,7 +524,7 @@ bool DeleteWholeDirectoryTree(mpt::PathString path)
|
||||||
|
|
||||||
#if defined(MPT_ENABLE_DYNBIND) || defined(MPT_ENABLE_TEMPFILE)
|
#if defined(MPT_ENABLE_DYNBIND) || defined(MPT_ENABLE_TEMPFILE)
|
||||||
|
|
||||||
mpt::PathString GetAppPath()
|
mpt::PathString GetExecutablePath()
|
||||||
{
|
{
|
||||||
std::vector<TCHAR> exeFileName(MAX_PATH);
|
std::vector<TCHAR> exeFileName(MAX_PATH);
|
||||||
while(GetModuleFileName(0, exeFileName.data(), mpt::saturate_cast<DWORD>(exeFileName.size())) >= exeFileName.size())
|
while(GetModuleFileName(0, exeFileName.data(), mpt::saturate_cast<DWORD>(exeFileName.size())) >= exeFileName.size())
|
||||||
|
@ -578,8 +578,8 @@ mpt::PathString GetTempDirectory()
|
||||||
return mpt::PathString::FromNative(tempPath.data());
|
return mpt::PathString::FromNative(tempPath.data());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// use app directory as fallback
|
// use exe directory as fallback
|
||||||
return mpt::GetAppPath();
|
return mpt::GetExecutablePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
mpt::PathString CreateTempFileName(const mpt::PathString &fileNamePrefix, const mpt::PathString &fileNameExtension)
|
mpt::PathString CreateTempFileName(const mpt::PathString &fileNamePrefix, const mpt::PathString &fileNameExtension)
|
||||||
|
@ -735,7 +735,7 @@ void SanitizeFilename(mpt::u8string &str)
|
||||||
}
|
}
|
||||||
#endif // MPT_USTRING_MODE_UTF8
|
#endif // MPT_USTRING_MODE_UTF8
|
||||||
|
|
||||||
#if defined(_MFC_VER)
|
#if defined(MPT_WITH_MFC)
|
||||||
void SanitizeFilename(CString &str)
|
void SanitizeFilename(CString &str)
|
||||||
{
|
{
|
||||||
for(int i = 0; i < str.GetLength(); i++)
|
for(int i = 0; i < str.GetLength(); i++)
|
||||||
|
@ -743,7 +743,7 @@ void SanitizeFilename(CString &str)
|
||||||
str.SetAt(i, SanitizeFilenameChar(str.GetAt(i)));
|
str.SetAt(i, SanitizeFilenameChar(str.GetAt(i)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // MFC
|
#endif // MPT_WITH_MFC
|
||||||
|
|
||||||
#endif // MODPLUG_TRACKER
|
#endif // MODPLUG_TRACKER
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ OPENMPT_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
|
||||||
#define MPT_DEPRECATED_PATH
|
#define MPT_DEPRECATED_PATH
|
||||||
//#define MPT_DEPRECATED_PATH MPT_DEPRECATED
|
//#define MPT_DEPRECATED_PATH [[deprecated]]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -120,9 +120,9 @@ public:
|
||||||
PathString GetDrive() const; // Drive letter + colon, e.g. "C:" or \\server\\share
|
PathString GetDrive() const; // Drive letter + colon, e.g. "C:" or \\server\\share
|
||||||
PathString GetDir() const; // Directory, e.g. "\OpenMPT\"
|
PathString GetDir() const; // Directory, e.g. "\OpenMPT\"
|
||||||
PathString GetPath() const; // Drive + Dir, e.g. "C:\OpenMPT\"
|
PathString GetPath() const; // Drive + Dir, e.g. "C:\OpenMPT\"
|
||||||
PathString GetFileName() const; // File name without extension, e.g. "mptrack"
|
PathString GetFileName() const; // File name without extension, e.g. "OpenMPT"
|
||||||
PathString GetFileExt() const; // Extension including dot, e.g. ".exe"
|
PathString GetFileExt() const; // Extension including dot, e.g. ".exe"
|
||||||
PathString GetFullFileName() const; // File name + extension, e.g. "mptrack.exe"
|
PathString GetFullFileName() const; // File name + extension, e.g. "OpenMPT.exe"
|
||||||
|
|
||||||
// Verify if this path represents a valid directory on the file system.
|
// Verify if this path represents a valid directory on the file system.
|
||||||
bool IsDirectory() const;
|
bool IsDirectory() const;
|
||||||
|
@ -204,27 +204,27 @@ public:
|
||||||
#endif
|
#endif
|
||||||
// conversions
|
// conversions
|
||||||
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
||||||
MPT_DEPRECATED_PATH std::string ToLocale() const { return mpt::ToCharset(mpt::CharsetLocale, path); }
|
MPT_DEPRECATED_PATH std::string ToLocale() const { return mpt::ToCharset(mpt::Charset::Locale, path); }
|
||||||
#endif
|
#endif
|
||||||
std::string ToUTF8() const { return mpt::ToCharset(mpt::CharsetUTF8, path); }
|
std::string ToUTF8() const { return mpt::ToCharset(mpt::Charset::UTF8, path); }
|
||||||
std::wstring ToWide() const { return mpt::ToWide(path); }
|
std::wstring ToWide() const { return mpt::ToWide(path); }
|
||||||
mpt::ustring ToUnicode() const { return mpt::ToUnicode(path); }
|
mpt::ustring ToUnicode() const { return mpt::ToUnicode(path); }
|
||||||
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
||||||
MPT_DEPRECATED_PATH static PathString FromLocale(const std::string &path) { return PathString(mpt::ToWin(mpt::CharsetLocale, path)); }
|
MPT_DEPRECATED_PATH static PathString FromLocale(const std::string &path) { return PathString(mpt::ToWin(mpt::Charset::Locale, path)); }
|
||||||
static PathString FromLocaleSilent(const std::string &path) { return PathString(mpt::ToWin(mpt::CharsetLocale, path)); }
|
static PathString FromLocaleSilent(const std::string &path) { return PathString(mpt::ToWin(mpt::Charset::Locale, path)); }
|
||||||
#endif
|
#endif
|
||||||
static PathString FromUTF8(const std::string &path) { return PathString(mpt::ToWin(mpt::CharsetUTF8, path)); }
|
static PathString FromUTF8(const std::string &path) { return PathString(mpt::ToWin(mpt::Charset::UTF8, path)); }
|
||||||
static PathString FromWide(const std::wstring &path) { return PathString(mpt::ToWin(path)); }
|
static PathString FromWide(const std::wstring &path) { return PathString(mpt::ToWin(path)); }
|
||||||
static PathString FromUnicode(const mpt::ustring &path) { return PathString(mpt::ToWin(path)); }
|
static PathString FromUnicode(const mpt::ustring &path) { return PathString(mpt::ToWin(path)); }
|
||||||
RawPathString AsNative() const { return path; }
|
RawPathString AsNative() const { return path; }
|
||||||
// Return native string, with possible \\?\ prefix if it exceeds MAX_PATH characters.
|
// Return native string, with possible \\?\ prefix if it exceeds MAX_PATH characters.
|
||||||
RawPathString AsNativePrefixed() const;
|
RawPathString AsNativePrefixed() const;
|
||||||
static PathString FromNative(const RawPathString &path) { return PathString(path); }
|
static PathString FromNative(const RawPathString &path) { return PathString(path); }
|
||||||
#if defined(_MFC_VER)
|
#if defined(MPT_WITH_MFC)
|
||||||
// CString TCHAR, so this is CHAR or WCHAR, depending on UNICODE
|
// CString TCHAR, so this is CHAR or WCHAR, depending on UNICODE
|
||||||
CString ToCString() const { return mpt::ToCString(path); }
|
CString ToCString() const { return mpt::ToCString(path); }
|
||||||
static PathString FromCString(const CString &path) { return PathString(mpt::ToWin(path)); }
|
static PathString FromCString(const CString &path) { return PathString(mpt::ToWin(path)); }
|
||||||
#endif
|
#endif // MPT_WITH_MFC
|
||||||
|
|
||||||
// Convert a path to its simplified form, i.e. remove ".\" and "..\" entries
|
// Convert a path to its simplified form, i.e. remove ".\" and "..\" entries
|
||||||
mpt::PathString Simplify() const;
|
mpt::PathString Simplify() const;
|
||||||
|
@ -234,39 +234,39 @@ public:
|
||||||
// conversions
|
// conversions
|
||||||
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
||||||
std::string ToLocale() const { return path; }
|
std::string ToLocale() const { return path; }
|
||||||
std::string ToUTF8() const { return mpt::ToCharset(mpt::CharsetUTF8, mpt::CharsetLocale, path); }
|
std::string ToUTF8() const { return mpt::ToCharset(mpt::Charset::UTF8, mpt::Charset::Locale, path); }
|
||||||
#if MPT_WSTRING_CONVERT
|
#if MPT_WSTRING_CONVERT
|
||||||
std::wstring ToWide() const { return mpt::ToWide(mpt::CharsetLocale, path); }
|
std::wstring ToWide() const { return mpt::ToWide(mpt::Charset::Locale, path); }
|
||||||
#endif
|
#endif
|
||||||
mpt::ustring ToUnicode() const { return mpt::ToUnicode(mpt::CharsetLocale, path); }
|
mpt::ustring ToUnicode() const { return mpt::ToUnicode(mpt::Charset::Locale, path); }
|
||||||
static PathString FromLocale(const std::string &path) { return PathString(path); }
|
static PathString FromLocale(const std::string &path) { return PathString(path); }
|
||||||
static PathString FromLocaleSilent(const std::string &path) { return PathString(path); }
|
static PathString FromLocaleSilent(const std::string &path) { return PathString(path); }
|
||||||
static PathString FromUTF8(const std::string &path) { return PathString(mpt::ToCharset(mpt::CharsetLocale, mpt::CharsetUTF8, path)); }
|
static PathString FromUTF8(const std::string &path) { return PathString(mpt::ToCharset(mpt::Charset::Locale, mpt::Charset::UTF8, path)); }
|
||||||
#if MPT_WSTRING_CONVERT
|
#if MPT_WSTRING_CONVERT
|
||||||
static PathString FromWide(const std::wstring &path) { return PathString(mpt::ToCharset(mpt::CharsetLocale, path)); }
|
static PathString FromWide(const std::wstring &path) { return PathString(mpt::ToCharset(mpt::Charset::Locale, path)); }
|
||||||
#endif
|
#endif
|
||||||
static PathString FromUnicode(const mpt::ustring &path) { return PathString(mpt::ToCharset(mpt::CharsetLocale, path)); }
|
static PathString FromUnicode(const mpt::ustring &path) { return PathString(mpt::ToCharset(mpt::Charset::Locale, path)); }
|
||||||
RawPathString AsNative() const { return path; }
|
RawPathString AsNative() const { return path; }
|
||||||
RawPathString AsNativePrefixed() const { return path; }
|
RawPathString AsNativePrefixed() const { return path; }
|
||||||
static PathString FromNative(const RawPathString &path) { return PathString(path); }
|
static PathString FromNative(const RawPathString &path) { return PathString(path); }
|
||||||
#else // !MPT_ENABLE_CHARSET_LOCALE
|
#else // !MPT_ENABLE_CHARSET_LOCALE
|
||||||
std::string ToUTF8() const { return path; }
|
std::string ToUTF8() const { return path; }
|
||||||
#if MPT_WSTRING_CONVERT
|
#if MPT_WSTRING_CONVERT
|
||||||
std::wstring ToWide() const { return mpt::ToWide(mpt::CharsetUTF8, path); }
|
std::wstring ToWide() const { return mpt::ToWide(mpt::Charset::UTF8, path); }
|
||||||
#endif
|
#endif
|
||||||
mpt::ustring ToUnicode() const { return mpt::ToUnicode(mpt::CharsetUTF8, path); }
|
mpt::ustring ToUnicode() const { return mpt::ToUnicode(mpt::Charset::UTF8, path); }
|
||||||
static PathString FromUTF8(const std::string &path) { return PathString(path); }
|
static PathString FromUTF8(const std::string &path) { return PathString(path); }
|
||||||
#if MPT_WSTRING_CONVERT
|
#if MPT_WSTRING_CONVERT
|
||||||
static PathString FromWide(const std::wstring &path) { return PathString(mpt::ToCharset(mpt::CharsetUTF8, path)); }
|
static PathString FromWide(const std::wstring &path) { return PathString(mpt::ToCharset(mpt::Charset::UTF8, path)); }
|
||||||
#endif
|
#endif
|
||||||
static PathString FromUnicode(const mpt::ustring &path) { return PathString(mpt::ToCharset(mpt::CharsetUTF8, path)); }
|
static PathString FromUnicode(const mpt::ustring &path) { return PathString(mpt::ToCharset(mpt::Charset::UTF8, path)); }
|
||||||
RawPathString AsNative() const { return path; }
|
RawPathString AsNative() const { return path; }
|
||||||
RawPathString AsNativePrefixed() const { return path; }
|
RawPathString AsNativePrefixed() const { return path; }
|
||||||
static PathString FromNative(const RawPathString &path) { return PathString(path); }
|
static PathString FromNative(const RawPathString &path) { return PathString(path); }
|
||||||
#endif // MPT_ENABLE_CHARSET_LOCALE
|
#endif // MPT_ENABLE_CHARSET_LOCALE
|
||||||
|
|
||||||
// Convert a path to its simplified form (currently only implemented on Windows)
|
// Convert a path to its simplified form (currently only implemented on Windows)
|
||||||
MPT_DEPRECATED mpt::PathString Simplify() const { return PathString(path); }
|
[[deprecated]] mpt::PathString Simplify() const { return PathString(path); }
|
||||||
|
|
||||||
#endif // MPT_OS_WINDOWS
|
#endif // MPT_OS_WINDOWS
|
||||||
|
|
||||||
|
@ -277,12 +277,12 @@ public:
|
||||||
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
||||||
#if MPT_OS_WINDOWS
|
#if MPT_OS_WINDOWS
|
||||||
#ifdef UNICODE
|
#ifdef UNICODE
|
||||||
MPT_DEPRECATED static inline std::string ToString(const mpt::PathString & x) { return mpt::ToCharset(mpt::CharsetLocale, x.ToUnicode()); }
|
[[deprecated]] static inline std::string ToString(const mpt::PathString & x) { return mpt::ToCharset(mpt::Charset::Locale, x.ToUnicode()); }
|
||||||
#else
|
#else
|
||||||
MPT_DEPRECATED_PATH static inline std::string ToString(const mpt::PathString & x) { return mpt::ToCharset(mpt::CharsetLocale, x.AsNative()); }
|
MPT_DEPRECATED_PATH static inline std::string ToString(const mpt::PathString & x) { return mpt::ToCharset(mpt::Charset::Locale, x.AsNative()); }
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
MPT_DEPRECATED_PATH static inline std::string ToString(const mpt::PathString & x) { return mpt::ToCharset(mpt::CharsetLocale, x.ToUnicode()); }
|
MPT_DEPRECATED_PATH static inline std::string ToString(const mpt::PathString & x) { return mpt::ToCharset(mpt::Charset::Locale, x.ToUnicode()); }
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
static inline mpt::ustring ToUString(const mpt::PathString & x) { return x.ToUnicode(); }
|
static inline mpt::ustring ToUString(const mpt::PathString & x) { return x.ToUnicode(); }
|
||||||
|
@ -339,8 +339,8 @@ bool DeleteWholeDirectoryTree(mpt::PathString path);
|
||||||
|
|
||||||
#if defined(MPT_ENABLE_DYNBIND) || defined(MPT_ENABLE_TEMPFILE)
|
#if defined(MPT_ENABLE_DYNBIND) || defined(MPT_ENABLE_TEMPFILE)
|
||||||
|
|
||||||
// Returns the application path or an empty string (if unknown), e.g. "C:\mptrack\"
|
// Returns the application executable path or an empty string (if unknown), e.g. "C:\mptrack\"
|
||||||
mpt::PathString GetAppPath();
|
mpt::PathString GetExecutablePath();
|
||||||
|
|
||||||
#endif // MPT_ENABLE_DYNBIND || MPT_ENABLE_TEMPFILE
|
#endif // MPT_ENABLE_DYNBIND || MPT_ENABLE_TEMPFILE
|
||||||
|
|
||||||
|
@ -418,20 +418,20 @@ void SanitizeFilename(mpt::u8string &str);
|
||||||
template <std::size_t size>
|
template <std::size_t size>
|
||||||
void SanitizeFilename(char (&buffer)[size])
|
void SanitizeFilename(char (&buffer)[size])
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(size > 0);
|
static_assert(size > 0);
|
||||||
SanitizeFilename(buffer, buffer + size);
|
SanitizeFilename(buffer, buffer + size);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <std::size_t size>
|
template <std::size_t size>
|
||||||
void SanitizeFilename(wchar_t (&buffer)[size])
|
void SanitizeFilename(wchar_t (&buffer)[size])
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(size > 0);
|
static_assert(size > 0);
|
||||||
SanitizeFilename(buffer, buffer + size);
|
SanitizeFilename(buffer, buffer + size);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(_MFC_VER)
|
#if defined(MPT_WITH_MFC)
|
||||||
void SanitizeFilename(CString &str);
|
void SanitizeFilename(CString &str);
|
||||||
#endif
|
#endif // MPT_WITH_MFC
|
||||||
|
|
||||||
#endif // MODPLUG_TRACKER
|
#endif // MODPLUG_TRACKER
|
||||||
|
|
||||||
|
|
|
@ -34,16 +34,16 @@ static T log2(T x)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static MPT_CONSTEXPR11_FUN int lower_bound_entropy_bits(unsigned int x)
|
static MPT_CONSTEXPR14_FUN int lower_bound_entropy_bits(unsigned int x)
|
||||||
{
|
{
|
||||||
return detail::lower_bound_entropy_bits(x);
|
return detail::lower_bound_entropy_bits(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static inline bool is_mask(T x)
|
static MPT_CONSTEXPR14_FUN bool is_mask(T x)
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(std::numeric_limits<T>::is_integer);
|
static_assert(std::numeric_limits<T>::is_integer);
|
||||||
typedef typename std::make_unsigned<T>::type unsigned_T;
|
typedef typename std::make_unsigned<T>::type unsigned_T;
|
||||||
unsigned_T ux = static_cast<unsigned_T>(x);
|
unsigned_T ux = static_cast<unsigned_T>(x);
|
||||||
unsigned_T mask = 0;
|
unsigned_T mask = 0;
|
||||||
|
@ -86,7 +86,7 @@ static T generate_timeseed()
|
||||||
{
|
{
|
||||||
uint64be time;
|
uint64be time;
|
||||||
time = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock().now().time_since_epoch()).count();
|
time = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock().now().time_since_epoch()).count();
|
||||||
mpt::byte bytes[sizeof(time)];
|
std::byte bytes[sizeof(time)];
|
||||||
std::memcpy(bytes, &time, sizeof(time));
|
std::memcpy(bytes, &time, sizeof(time));
|
||||||
hash(std::begin(bytes), std::end(bytes));
|
hash(std::begin(bytes), std::end(bytes));
|
||||||
}
|
}
|
||||||
|
@ -94,7 +94,7 @@ static T generate_timeseed()
|
||||||
{
|
{
|
||||||
uint64be time;
|
uint64be time;
|
||||||
time = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock().now().time_since_epoch()).count();
|
time = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock().now().time_since_epoch()).count();
|
||||||
mpt::byte bytes[sizeof(time)];
|
std::byte bytes[sizeof(time)];
|
||||||
std::memcpy(bytes, &time, sizeof(time));
|
std::memcpy(bytes, &time, sizeof(time));
|
||||||
hash(std::begin(bytes), std::end(bytes));
|
hash(std::begin(bytes), std::end(bytes));
|
||||||
}
|
}
|
||||||
|
@ -126,8 +126,19 @@ crand::result_type crand::operator()()
|
||||||
#endif // MODPLUG_TRACKER
|
#endif // MODPLUG_TRACKER
|
||||||
|
|
||||||
sane_random_device::sane_random_device()
|
sane_random_device::sane_random_device()
|
||||||
: rd_reliable(rd.entropy() > 0.0)
|
: rd_reliable(false)
|
||||||
{
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
prd = std::make_unique<std::random_device>();
|
||||||
|
rd_reliable = ((*prd).entropy() > 0.0);
|
||||||
|
} MPT_EXCEPTION_CATCH_OUT_OF_MEMORY(e)
|
||||||
|
{
|
||||||
|
MPT_EXCEPTION_RETHROW_OUT_OF_MEMORY(e);
|
||||||
|
} catch(const std::exception &)
|
||||||
|
{
|
||||||
|
rd_reliable = false;
|
||||||
|
}
|
||||||
if(!rd_reliable)
|
if(!rd_reliable)
|
||||||
{
|
{
|
||||||
init_fallback();
|
init_fallback();
|
||||||
|
@ -136,9 +147,19 @@ sane_random_device::sane_random_device()
|
||||||
|
|
||||||
sane_random_device::sane_random_device(const std::string & token_)
|
sane_random_device::sane_random_device(const std::string & token_)
|
||||||
: token(token_)
|
: token(token_)
|
||||||
, rd(token)
|
, rd_reliable(false)
|
||||||
, rd_reliable(rd.entropy() > 0.0)
|
|
||||||
{
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
prd = std::make_unique<std::random_device>(token);
|
||||||
|
rd_reliable = ((*prd).entropy() > 0.0);
|
||||||
|
} MPT_EXCEPTION_CATCH_OUT_OF_MEMORY(e)
|
||||||
|
{
|
||||||
|
MPT_EXCEPTION_RETHROW_OUT_OF_MEMORY(e);
|
||||||
|
} catch(const std::exception &)
|
||||||
|
{
|
||||||
|
rd_reliable = false;
|
||||||
|
}
|
||||||
if(!rd_reliable)
|
if(!rd_reliable)
|
||||||
{
|
{
|
||||||
init_fallback();
|
init_fallback();
|
||||||
|
@ -160,7 +181,7 @@ void sane_random_device::init_fallback()
|
||||||
seeds.push_back(static_cast<unsigned int>(static_cast<unsigned char>(token[i])));
|
seeds.push_back(static_cast<unsigned int>(static_cast<unsigned char>(token[i])));
|
||||||
}
|
}
|
||||||
std::seed_seq seed(seeds.begin(), seeds.end());
|
std::seed_seq seed(seeds.begin(), seeds.end());
|
||||||
rd_fallback = mpt::make_unique<std::mt19937>(seed);
|
rd_fallback = std::make_unique<std::mt19937>(seed);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
uint64 seed_val = mpt::generate_timeseed<uint64>();
|
uint64 seed_val = mpt::generate_timeseed<uint64>();
|
||||||
|
@ -168,53 +189,59 @@ void sane_random_device::init_fallback()
|
||||||
seeds[0] = static_cast<uint32>(seed_val >> 32);
|
seeds[0] = static_cast<uint32>(seed_val >> 32);
|
||||||
seeds[1] = static_cast<uint32>(seed_val >> 0);
|
seeds[1] = static_cast<uint32>(seed_val >> 0);
|
||||||
std::seed_seq seed(seeds + 0, seeds + 2);
|
std::seed_seq seed(seeds + 0, seeds + 2);
|
||||||
rd_fallback = mpt::make_unique<std::mt19937>(seed);
|
rd_fallback = std::make_unique<std::mt19937>(seed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sane_random_device::result_type sane_random_device::operator()()
|
sane_random_device::result_type sane_random_device::operator()()
|
||||||
{
|
{
|
||||||
MPT_LOCK_GUARD<mpt::mutex> l(m);
|
mpt::lock_guard<mpt::mutex> l(m);
|
||||||
result_type result = 0;
|
result_type result = 0;
|
||||||
try
|
if(prd)
|
||||||
{
|
{
|
||||||
if(rd.min() != 0 || !mpt::is_mask(rd.max()))
|
try
|
||||||
{ // insane std::random_device
|
{
|
||||||
// This implementation is not exactly uniformly distributed but good enough
|
if constexpr(std::random_device::min() != 0 || !mpt::is_mask(std::random_device::max()))
|
||||||
// for OpenMPT.
|
{ // insane std::random_device
|
||||||
double rd_min = static_cast<double>(rd.min());
|
// This implementation is not exactly uniformly distributed but good enough
|
||||||
double rd_max = static_cast<double>(rd.max());
|
// for OpenMPT.
|
||||||
double rd_range = rd_max - rd_min;
|
double rd_min = static_cast<double>(std::random_device::min());
|
||||||
double rd_size = rd_range + 1.0;
|
double rd_max = static_cast<double>(std::random_device::max());
|
||||||
double rd_entropy = mpt::log2(rd_size);
|
double rd_range = rd_max - rd_min;
|
||||||
int iterations = static_cast<int>(std::ceil(result_bits() / rd_entropy));
|
double rd_size = rd_range + 1.0;
|
||||||
double tmp = 0.0;
|
double rd_entropy = mpt::log2(rd_size);
|
||||||
for(int i = 0; i < iterations; ++i)
|
int iterations = static_cast<int>(std::ceil(result_bits() / rd_entropy));
|
||||||
{
|
double tmp = 0.0;
|
||||||
tmp = (tmp * rd_size) + (static_cast<double>(rd()) - rd_min);
|
for(int i = 0; i < iterations; ++i)
|
||||||
}
|
|
||||||
double result_01 = std::floor(tmp / std::pow(rd_size, iterations));
|
|
||||||
result = static_cast<result_type>(std::floor(result_01 * (static_cast<double>(max() - min()) + 1.0))) + min();
|
|
||||||
} else
|
|
||||||
{ // sane std::random_device
|
|
||||||
result = 0;
|
|
||||||
std::size_t rd_bits = mpt::lower_bound_entropy_bits(rd.max());
|
|
||||||
for(std::size_t entropy = 0; entropy < (sizeof(result_type) * 8); entropy += rd_bits)
|
|
||||||
{
|
|
||||||
if(rd_bits < (sizeof(result_type) * 8))
|
|
||||||
{
|
{
|
||||||
result = (result << rd_bits) | static_cast<result_type>(rd());
|
tmp = (tmp * rd_size) + (static_cast<double>((*prd)()) - rd_min);
|
||||||
} else
|
}
|
||||||
|
double result_01 = std::floor(tmp / std::pow(rd_size, iterations));
|
||||||
|
result = static_cast<result_type>(std::floor(result_01 * (static_cast<double>(max() - min()) + 1.0))) + min();
|
||||||
|
} else
|
||||||
|
{ // sane std::random_device
|
||||||
|
result = 0;
|
||||||
|
std::size_t rd_bits = mpt::lower_bound_entropy_bits(std::random_device::max());
|
||||||
|
for(std::size_t entropy = 0; entropy < (sizeof(result_type) * 8); entropy += rd_bits)
|
||||||
{
|
{
|
||||||
result = result | static_cast<result_type>(rd());
|
if(rd_bits < (sizeof(result_type) * 8))
|
||||||
|
{
|
||||||
|
result = (result << rd_bits) | static_cast<result_type>((*prd)());
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
result = result | static_cast<result_type>((*prd)());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch(const std::exception &)
|
||||||
|
{
|
||||||
|
rd_reliable = false;
|
||||||
|
init_fallback();
|
||||||
}
|
}
|
||||||
} catch(const std::exception &)
|
} else
|
||||||
{
|
{
|
||||||
rd_reliable = false;
|
rd_reliable = false;
|
||||||
init_fallback();
|
|
||||||
}
|
}
|
||||||
if(!rd_reliable)
|
if(!rd_reliable)
|
||||||
{ // std::random_device is unreliable
|
{ // std::random_device is unreliable
|
||||||
|
|
|
@ -44,50 +44,113 @@ namespace mpt
|
||||||
|
|
||||||
|
|
||||||
#ifdef MPT_BUILD_FUZZER
|
#ifdef MPT_BUILD_FUZZER
|
||||||
static const uint32 FUZZER_RNG_SEED = 3141592653u; // pi
|
static constexpr uint32 FUZZER_RNG_SEED = 3141592653u; // pi
|
||||||
#endif // MPT_BUILD_FUZZER
|
#endif // MPT_BUILD_FUZZER
|
||||||
|
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
|
||||||
MPT_CONSTEXPR11_FUN int lower_bound_entropy_bits(unsigned int x)
|
MPT_CONSTEXPR14_FUN int lower_bound_entropy_bits(unsigned int x)
|
||||||
{
|
{
|
||||||
// easy to compile-time evaluate even for stupid compilers
|
if(x >= 0xffffffffu)
|
||||||
return
|
{
|
||||||
x >= 0xffffffffu ? 32 :
|
return 32;
|
||||||
x >= 0x7fffffffu ? 31 :
|
} else if(x >= 0x7fffffffu)
|
||||||
x >= 0x3fffffffu ? 30 :
|
{
|
||||||
x >= 0x1fffffffu ? 29 :
|
return 31;
|
||||||
x >= 0x0fffffffu ? 28 :
|
} else if(x >= 0x3fffffffu)
|
||||||
x >= 0x07ffffffu ? 27 :
|
{
|
||||||
x >= 0x03ffffffu ? 26 :
|
return 30;
|
||||||
x >= 0x01ffffffu ? 25 :
|
} else if(x >= 0x1fffffffu)
|
||||||
x >= 0x00ffffffu ? 24 :
|
{
|
||||||
x >= 0x007fffffu ? 23 :
|
return 29;
|
||||||
x >= 0x003fffffu ? 22 :
|
} else if(x >= 0x0fffffffu)
|
||||||
x >= 0x001fffffu ? 21 :
|
{
|
||||||
x >= 0x000fffffu ? 20 :
|
return 28;
|
||||||
x >= 0x0007ffffu ? 19 :
|
} else if(x >= 0x07ffffffu)
|
||||||
x >= 0x0003ffffu ? 18 :
|
{
|
||||||
x >= 0x0001ffffu ? 17 :
|
return 27;
|
||||||
x >= 0x0000ffffu ? 16 :
|
} else if(x >= 0x03ffffffu)
|
||||||
x >= 0x00007fffu ? 15 :
|
{
|
||||||
x >= 0x00003fffu ? 14 :
|
return 26;
|
||||||
x >= 0x00001fffu ? 13 :
|
} else if(x >= 0x01ffffffu)
|
||||||
x >= 0x00000fffu ? 12 :
|
{
|
||||||
x >= 0x000007ffu ? 11 :
|
return 25;
|
||||||
x >= 0x000003ffu ? 10 :
|
} else if(x >= 0x00ffffffu)
|
||||||
x >= 0x000001ffu ? 9 :
|
{
|
||||||
x >= 0x000000ffu ? 8 :
|
return 24;
|
||||||
x >= 0x0000007fu ? 7 :
|
} else if(x >= 0x007fffffu)
|
||||||
x >= 0x0000003fu ? 6 :
|
{
|
||||||
x >= 0x0000001fu ? 5 :
|
return 23;
|
||||||
x >= 0x0000000fu ? 4 :
|
} else if(x >= 0x003fffffu)
|
||||||
x >= 0x00000007u ? 3 :
|
{
|
||||||
x >= 0x00000003u ? 2 :
|
return 22;
|
||||||
x >= 0x00000001u ? 1 :
|
} else if(x >= 0x001fffffu)
|
||||||
0;
|
{
|
||||||
|
return 21;
|
||||||
|
} else if(x >= 0x000fffffu)
|
||||||
|
{
|
||||||
|
return 20;
|
||||||
|
} else if(x >= 0x0007ffffu)
|
||||||
|
{
|
||||||
|
return 19;
|
||||||
|
} else if(x >= 0x0003ffffu)
|
||||||
|
{
|
||||||
|
return 18;
|
||||||
|
} else if(x >= 0x0001ffffu)
|
||||||
|
{
|
||||||
|
return 17;
|
||||||
|
} else if(x >= 0x0000ffffu)
|
||||||
|
{
|
||||||
|
return 16;
|
||||||
|
} else if(x >= 0x00007fffu)
|
||||||
|
{
|
||||||
|
return 15;
|
||||||
|
} else if(x >= 0x00003fffu)
|
||||||
|
{
|
||||||
|
return 14;
|
||||||
|
} else if(x >= 0x00001fffu)
|
||||||
|
{
|
||||||
|
return 13;
|
||||||
|
} else if(x >= 0x00000fffu)
|
||||||
|
{
|
||||||
|
return 12;
|
||||||
|
} else if(x >= 0x000007ffu)
|
||||||
|
{
|
||||||
|
return 11;
|
||||||
|
} else if(x >= 0x000003ffu)
|
||||||
|
{
|
||||||
|
return 10;
|
||||||
|
} else if(x >= 0x000001ffu)
|
||||||
|
{
|
||||||
|
return 9;
|
||||||
|
} else if(x >= 0x000000ffu)
|
||||||
|
{
|
||||||
|
return 8;
|
||||||
|
} else if(x >= 0x0000007fu)
|
||||||
|
{
|
||||||
|
return 7;
|
||||||
|
} else if(x >= 0x0000003fu)
|
||||||
|
{
|
||||||
|
return 6;
|
||||||
|
} else if(x >= 0x0000001fu)
|
||||||
|
{
|
||||||
|
return 5;
|
||||||
|
} else if(x >= 0x0000000fu)
|
||||||
|
{
|
||||||
|
return 4;
|
||||||
|
} else if(x >= 0x00000007u)
|
||||||
|
{
|
||||||
|
return 3;
|
||||||
|
} else if(x >= 0x00000003u)
|
||||||
|
{
|
||||||
|
return 2;
|
||||||
|
} else if(x >= 0x00000001u)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -111,15 +174,15 @@ template <typename Trng> struct engine_traits
|
||||||
template <typename T, typename Trng>
|
template <typename T, typename Trng>
|
||||||
inline T random(Trng & rng)
|
inline T random(Trng & rng)
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(std::numeric_limits<T>::is_integer);
|
static_assert(std::numeric_limits<T>::is_integer);
|
||||||
typedef typename std::make_unsigned<T>::type unsigned_T;
|
typedef typename std::make_unsigned<T>::type unsigned_T;
|
||||||
const unsigned int rng_bits = mpt::engine_traits<Trng>::result_bits();
|
const unsigned int rng_bits = mpt::engine_traits<Trng>::result_bits();
|
||||||
unsigned_T result = 0;
|
unsigned_T result = 0;
|
||||||
for(std::size_t entropy = 0; entropy < (sizeof(T) * 8); entropy += rng_bits)
|
for(std::size_t entropy = 0; entropy < (sizeof(T) * 8); entropy += rng_bits)
|
||||||
{
|
{
|
||||||
MPT_CONSTANT_IF(rng_bits < (sizeof(T) * 8))
|
if constexpr(rng_bits < (sizeof(T) * 8))
|
||||||
{
|
{
|
||||||
MPT_CONSTEXPR11_VAR unsigned int shift_bits = rng_bits % (sizeof(T) * 8); // silence utterly stupid MSVC and GCC warnings about shifting by too big amount (in which case this branch is not even taken however)
|
constexpr unsigned int shift_bits = rng_bits % (sizeof(T) * 8); // silence utterly stupid MSVC and GCC warnings about shifting by too big amount (in which case this branch is not even taken however)
|
||||||
result = (result << shift_bits) ^ static_cast<unsigned_T>(rng());
|
result = (result << shift_bits) ^ static_cast<unsigned_T>(rng());
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
|
@ -132,22 +195,22 @@ inline T random(Trng & rng)
|
||||||
template <typename T, std::size_t required_entropy_bits, typename Trng>
|
template <typename T, std::size_t required_entropy_bits, typename Trng>
|
||||||
inline T random(Trng & rng)
|
inline T random(Trng & rng)
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(std::numeric_limits<T>::is_integer);
|
static_assert(std::numeric_limits<T>::is_integer);
|
||||||
typedef typename std::make_unsigned<T>::type unsigned_T;
|
typedef typename std::make_unsigned<T>::type unsigned_T;
|
||||||
const unsigned int rng_bits = mpt::engine_traits<Trng>::result_bits();
|
const unsigned int rng_bits = mpt::engine_traits<Trng>::result_bits();
|
||||||
unsigned_T result = 0;
|
unsigned_T result = 0;
|
||||||
for(std::size_t entropy = 0; entropy < std::min<std::size_t>(required_entropy_bits, sizeof(T) * 8); entropy += rng_bits)
|
for(std::size_t entropy = 0; entropy < std::min(required_entropy_bits, sizeof(T) * 8); entropy += rng_bits)
|
||||||
{
|
{
|
||||||
MPT_CONSTANT_IF(rng_bits < (sizeof(T) * 8))
|
if constexpr(rng_bits < (sizeof(T) * 8))
|
||||||
{
|
{
|
||||||
MPT_CONSTEXPR11_VAR unsigned int shift_bits = rng_bits % (sizeof(T) * 8); // silence utterly stupid MSVC and GCC warnings about shifting by too big amount (in which case this branch is not even taken however)
|
constexpr unsigned int shift_bits = rng_bits % (sizeof(T) * 8); // silence utterly stupid MSVC and GCC warnings about shifting by too big amount (in which case this branch is not even taken however)
|
||||||
result = (result << shift_bits) ^ static_cast<unsigned_T>(rng());
|
result = (result << shift_bits) ^ static_cast<unsigned_T>(rng());
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
result = static_cast<unsigned_T>(rng());
|
result = static_cast<unsigned_T>(rng());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MPT_CONSTANT_IF(required_entropy_bits >= (sizeof(T) * 8))
|
if constexpr(required_entropy_bits >= (sizeof(T) * 8))
|
||||||
{
|
{
|
||||||
return static_cast<T>(result);
|
return static_cast<T>(result);
|
||||||
} else
|
} else
|
||||||
|
@ -159,15 +222,15 @@ inline T random(Trng & rng)
|
||||||
template <typename T, typename Trng>
|
template <typename T, typename Trng>
|
||||||
inline T random(Trng & rng, std::size_t required_entropy_bits)
|
inline T random(Trng & rng, std::size_t required_entropy_bits)
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(std::numeric_limits<T>::is_integer);
|
static_assert(std::numeric_limits<T>::is_integer);
|
||||||
typedef typename std::make_unsigned<T>::type unsigned_T;
|
typedef typename std::make_unsigned<T>::type unsigned_T;
|
||||||
const unsigned int rng_bits = mpt::engine_traits<Trng>::result_bits();
|
const unsigned int rng_bits = mpt::engine_traits<Trng>::result_bits();
|
||||||
unsigned_T result = 0;
|
unsigned_T result = 0;
|
||||||
for(std::size_t entropy = 0; entropy < std::min<std::size_t>(required_entropy_bits, sizeof(T) * 8); entropy += rng_bits)
|
for(std::size_t entropy = 0; entropy < std::min(required_entropy_bits, sizeof(T) * 8); entropy += rng_bits)
|
||||||
{
|
{
|
||||||
MPT_CONSTANT_IF(rng_bits < (sizeof(T) * 8))
|
if constexpr(rng_bits < (sizeof(T) * 8))
|
||||||
{
|
{
|
||||||
MPT_CONSTEXPR11_VAR unsigned int shift_bits = rng_bits % (sizeof(T) * 8); // silence utterly stupid MSVC and GCC warnings about shifting by too big amount (in which case this branch is not even taken however)
|
constexpr unsigned int shift_bits = rng_bits % (sizeof(T) * 8); // silence utterly stupid MSVC and GCC warnings about shifting by too big amount (in which case this branch is not even taken however)
|
||||||
result = (result << shift_bits) ^ static_cast<unsigned_T>(rng());
|
result = (result << shift_bits) ^ static_cast<unsigned_T>(rng());
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
|
@ -183,20 +246,6 @@ inline T random(Trng & rng, std::size_t required_entropy_bits)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Tf> struct float_traits { };
|
|
||||||
template <> struct float_traits<float> {
|
|
||||||
typedef uint32 mantissa_uint_type;
|
|
||||||
enum : int { mantissa_bits = 24 };
|
|
||||||
};
|
|
||||||
template <> struct float_traits<double> {
|
|
||||||
typedef uint64 mantissa_uint_type;
|
|
||||||
enum : int { mantissa_bits = 53 };
|
|
||||||
};
|
|
||||||
template <> struct float_traits<long double> {
|
|
||||||
typedef uint64 mantissa_uint_type;
|
|
||||||
enum : int { mantissa_bits = 63 };
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct uniform_real_distribution
|
struct uniform_real_distribution
|
||||||
{
|
{
|
||||||
|
@ -213,9 +262,8 @@ public:
|
||||||
template <typename Trng>
|
template <typename Trng>
|
||||||
inline T operator()(Trng & rng) const
|
inline T operator()(Trng & rng) const
|
||||||
{
|
{
|
||||||
typedef typename float_traits<T>::mantissa_uint_type uint_type;
|
const int mantissa_bits = std::numeric_limits<T>::digits;
|
||||||
const int bits = float_traits<T>::mantissa_bits;
|
return ((b - a) * static_cast<T>(mpt::random<uint64, mantissa_bits>(rng)) / static_cast<T>((static_cast<uint64>(1u) << mantissa_bits))) + a;
|
||||||
return ((b - a) * static_cast<T>(mpt::random<uint_type, bits>(rng)) / static_cast<T>((static_cast<uint_type>(1u) << bits))) + a;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -223,7 +271,7 @@ public:
|
||||||
template <typename T, typename Trng>
|
template <typename T, typename Trng>
|
||||||
inline T random(Trng & rng, T min, T max)
|
inline T random(Trng & rng, T min, T max)
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(!std::numeric_limits<T>::is_integer);
|
static_assert(!std::numeric_limits<T>::is_integer);
|
||||||
typedef mpt::uniform_real_distribution<T> dis_type;
|
typedef mpt::uniform_real_distribution<T> dis_type;
|
||||||
dis_type dis(min, max);
|
dis_type dis(min, max);
|
||||||
return static_cast<T>(dis(rng));
|
return static_cast<T>(dis(rng));
|
||||||
|
@ -265,12 +313,12 @@ public:
|
||||||
}
|
}
|
||||||
static MPT_CONSTEXPR11_FUN result_type max()
|
static MPT_CONSTEXPR11_FUN result_type max()
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(((result_mask >> result_shift) << result_shift) == result_mask);
|
static_assert(((result_mask >> result_shift) << result_shift) == result_mask);
|
||||||
return static_cast<result_type>(result_mask >> result_shift);
|
return static_cast<result_type>(result_mask >> result_shift);
|
||||||
}
|
}
|
||||||
static MPT_CONSTEXPR11_FUN int result_bits()
|
static MPT_CONSTEXPR11_FUN int result_bits()
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(((static_cast<Tstate>(1) << result_bits_) - 1) == (result_mask >> result_shift));
|
static_assert(((static_cast<Tstate>(1) << result_bits_) - 1) == (result_mask >> result_shift));
|
||||||
return result_bits_;
|
return result_bits_;
|
||||||
}
|
}
|
||||||
inline result_type operator()()
|
inline result_type operator()()
|
||||||
|
@ -292,6 +340,59 @@ typedef lcg<uint32, uint16, 0u, 214013u, 2531011u, 0x7fff0000u, 16, 15> lcg_msvc
|
||||||
typedef lcg<uint32, uint16, 0x80000000u, 1103515245u, 12345u, 0x7fff0000u, 16, 15> lcg_c99;
|
typedef lcg<uint32, uint16, 0x80000000u, 1103515245u, 12345u, 0x7fff0000u, 16, 15> lcg_c99;
|
||||||
typedef lcg<uint64, uint32, 0ull, 6364136223846793005ull, 1ull, 0xffffffff00000000ull, 32, 32> lcg_musl;
|
typedef lcg<uint64, uint32, 0ull, 6364136223846793005ull, 1ull, 0xffffffff00000000ull, 32, 32> lcg_musl;
|
||||||
|
|
||||||
|
template <typename Tstate, typename Tvalue, Tstate x1, Tstate x2, Tstate x3, Tstate x4, int rol1, int rol2>
|
||||||
|
class modplug
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Tstate state_type;
|
||||||
|
typedef Tvalue result_type;
|
||||||
|
private:
|
||||||
|
state_type state1;
|
||||||
|
state_type state2;
|
||||||
|
public:
|
||||||
|
template <typename Trng>
|
||||||
|
explicit inline modplug(Trng &rd)
|
||||||
|
: state1(mpt::random<state_type>(rd))
|
||||||
|
, state2(mpt::random<state_type>(rd))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
explicit inline modplug(state_type seed1, state_type seed2)
|
||||||
|
: state1(seed1)
|
||||||
|
, state2(seed2)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
static MPT_CONSTEXPR11_FUN result_type min()
|
||||||
|
{
|
||||||
|
return static_cast<result_type>(0);
|
||||||
|
}
|
||||||
|
static MPT_CONSTEXPR11_FUN result_type max()
|
||||||
|
{
|
||||||
|
return std::numeric_limits<result_type>::max();
|
||||||
|
}
|
||||||
|
static MPT_CONSTEXPR11_FUN int result_bits()
|
||||||
|
{
|
||||||
|
static_assert(std::is_integral<result_type>::value);
|
||||||
|
static_assert(std::is_unsigned<result_type>::value);
|
||||||
|
return std::numeric_limits<result_type>::digits;
|
||||||
|
}
|
||||||
|
inline result_type operator()()
|
||||||
|
{
|
||||||
|
state_type a = state1;
|
||||||
|
state_type b = state2;
|
||||||
|
a = mpt::rotl(a, rol1);
|
||||||
|
a ^= x1;
|
||||||
|
a += x2 + (b * x3);
|
||||||
|
b += mpt::rotl(a, rol2) * x4;
|
||||||
|
state1 = a;
|
||||||
|
state2 = b;
|
||||||
|
result_type result = static_cast<result_type>(b);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef modplug<uint32, uint32, 0x10204080u, 0x78649E7Du, 4, 5, 1, 16> modplug_dither;
|
||||||
|
|
||||||
} // namespace rng
|
} // namespace rng
|
||||||
|
|
||||||
|
|
||||||
|
@ -325,7 +426,7 @@ public:
|
||||||
{
|
{
|
||||||
return RAND_MAX;
|
return RAND_MAX;
|
||||||
}
|
}
|
||||||
static MPT_CONSTEXPR11_FUN int result_bits()
|
static MPT_CONSTEXPR14_FUN int result_bits()
|
||||||
{
|
{
|
||||||
return detail::lower_bound_entropy_bits(RAND_MAX);
|
return detail::lower_bound_entropy_bits(RAND_MAX);
|
||||||
}
|
}
|
||||||
|
@ -348,7 +449,7 @@ class sane_random_device
|
||||||
private:
|
private:
|
||||||
mpt::mutex m;
|
mpt::mutex m;
|
||||||
std::string token;
|
std::string token;
|
||||||
std::random_device rd;
|
std::unique_ptr<std::random_device> prd;
|
||||||
bool rd_reliable;
|
bool rd_reliable;
|
||||||
std::unique_ptr<std::mt19937> rd_fallback;
|
std::unique_ptr<std::mt19937> rd_fallback;
|
||||||
public:
|
public:
|
||||||
|
@ -410,7 +511,7 @@ template <> struct engine_traits<std::mt19937> {
|
||||||
static MPT_CONSTEXPR11_FUN int result_bits() { return rng_type::word_size; }
|
static MPT_CONSTEXPR11_FUN int result_bits() { return rng_type::word_size; }
|
||||||
template<typename Trd> static inline rng_type make(Trd & rd)
|
template<typename Trd> static inline rng_type make(Trd & rd)
|
||||||
{
|
{
|
||||||
std::unique_ptr<mpt::seed_seq_values<seed_bits / sizeof(unsigned int)>> values = mpt::make_unique<mpt::seed_seq_values<seed_bits / sizeof(unsigned int)>>(rd);
|
std::unique_ptr<mpt::seed_seq_values<seed_bits / sizeof(unsigned int)>> values = std::make_unique<mpt::seed_seq_values<seed_bits / sizeof(unsigned int)>>(rd);
|
||||||
std::seed_seq seed(values->begin(), values->end());
|
std::seed_seq seed(values->begin(), values->end());
|
||||||
return rng_type(seed);
|
return rng_type(seed);
|
||||||
}
|
}
|
||||||
|
@ -423,7 +524,7 @@ template <> struct engine_traits<std::mt19937_64> {
|
||||||
static MPT_CONSTEXPR11_FUN int result_bits() { return rng_type::word_size; }
|
static MPT_CONSTEXPR11_FUN int result_bits() { return rng_type::word_size; }
|
||||||
template<typename Trd> static inline rng_type make(Trd & rd)
|
template<typename Trd> static inline rng_type make(Trd & rd)
|
||||||
{
|
{
|
||||||
std::unique_ptr<mpt::seed_seq_values<seed_bits / sizeof(unsigned int)>> values = mpt::make_unique<mpt::seed_seq_values<seed_bits / sizeof(unsigned int)>>(rd);
|
std::unique_ptr<mpt::seed_seq_values<seed_bits / sizeof(unsigned int)>> values = std::make_unique<mpt::seed_seq_values<seed_bits / sizeof(unsigned int)>>(rd);
|
||||||
std::seed_seq seed(values->begin(), values->end());
|
std::seed_seq seed(values->begin(), values->end());
|
||||||
return rng_type(seed);
|
return rng_type(seed);
|
||||||
}
|
}
|
||||||
|
@ -534,7 +635,7 @@ public:
|
||||||
}
|
}
|
||||||
result_type operator()()
|
result_type operator()()
|
||||||
{
|
{
|
||||||
MPT_LOCK_GUARD<mpt::mutex> l(m);
|
mpt::lock_guard<mpt::mutex> l(m);
|
||||||
return mpt::random<unsigned int>(rng);
|
return mpt::random<unsigned int>(rng);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -609,7 +710,7 @@ public:
|
||||||
public:
|
public:
|
||||||
typename engine_traits<Trng>::result_type operator()()
|
typename engine_traits<Trng>::result_type operator()()
|
||||||
{
|
{
|
||||||
MPT_LOCK_GUARD<mpt::mutex> l(m);
|
mpt::lock_guard<mpt::mutex> l(m);
|
||||||
return Trng::operator()();
|
return Trng::operator()();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* mptSpan.h
|
* mptSpan.h
|
||||||
* ---------
|
* ---------
|
||||||
* Purpose: Various useful utility functions.
|
* Purpose: C++20 span.
|
||||||
* Notes : (currently none)
|
* Notes : (currently none)
|
||||||
* Authors: OpenMPT Devs
|
* Authors: OpenMPT Devs
|
||||||
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
|
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
|
||||||
|
@ -15,8 +15,14 @@
|
||||||
|
|
||||||
#include "mptBaseTypes.h"
|
#include "mptBaseTypes.h"
|
||||||
|
|
||||||
|
#if MPT_CXX_AT_LEAST(20)
|
||||||
|
#include <array>
|
||||||
|
#include <span>
|
||||||
|
#else // !C++20
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
#include <type_traits>
|
||||||
|
#endif // C++20
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -29,6 +35,12 @@ namespace mpt {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if MPT_CXX_AT_LEAST(20)
|
||||||
|
|
||||||
|
using std::span;
|
||||||
|
|
||||||
|
#else // !C++20
|
||||||
|
|
||||||
// Simplified version of gsl::span.
|
// Simplified version of gsl::span.
|
||||||
// Non-owning read-only or read-write view into a contiguous block of T
|
// Non-owning read-only or read-write view into a contiguous block of T
|
||||||
// objects, i.e. equivalent to a (beg,end) or (data,size) tuple.
|
// objects, i.e. equivalent to a (beg,end) or (data,size) tuple.
|
||||||
|
@ -40,18 +52,18 @@ class span
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
typedef std::size_t size_type;
|
using element_type = T;
|
||||||
|
using value_type = typename std::remove_cv<T>::type;
|
||||||
|
using index_type = std::size_t;
|
||||||
|
using pointer = T *;
|
||||||
|
using const_pointer = const T *;
|
||||||
|
using reference = T &;
|
||||||
|
using const_reference = const T &;
|
||||||
|
|
||||||
typedef T value_type;
|
using iterator = pointer;
|
||||||
typedef T & reference;
|
using const_iterator = const_pointer;
|
||||||
typedef T * pointer;
|
|
||||||
typedef const T * const_pointer;
|
|
||||||
typedef const T & const_reference;
|
|
||||||
|
|
||||||
typedef pointer iterator;
|
using difference_type = typename std::iterator_traits<iterator>::difference_type;
|
||||||
typedef const_pointer const_iterator;
|
|
||||||
|
|
||||||
typedef typename std::iterator_traits<iterator>::difference_type difference_type;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -60,22 +72,26 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
span() : m_beg(nullptr), m_end(nullptr) { }
|
span() noexcept : m_beg(nullptr), m_end(nullptr) { }
|
||||||
|
|
||||||
span(pointer beg, pointer end) : m_beg(beg), m_end(end) { }
|
span(pointer beg, pointer end) : m_beg(beg), m_end(end) { }
|
||||||
|
|
||||||
span(pointer data, size_type size) : m_beg(data), m_end(data + size) { }
|
span(pointer data, index_type size) : m_beg(data), m_end(data + size) { }
|
||||||
|
|
||||||
template <typename U, std::size_t N> span(U (&arr)[N]) : m_beg(arr), m_end(arr + N) { }
|
template <std::size_t N> span(element_type (&arr)[N]) : m_beg(arr), m_end(arr + N) { }
|
||||||
|
|
||||||
template <typename Cont> span(Cont &cont) : m_beg(cont.empty() ? nullptr : &(cont[0])), m_end(cont.empty() ? nullptr : &(cont[0]) + cont.size()) { }
|
template <std::size_t N> span(std::array<value_type, N> &arr) : m_beg(arr.data()), m_end(arr.data() + arr.size()) { }
|
||||||
|
|
||||||
|
template <std::size_t N> span(const std::array<value_type, N> &arr) : m_beg(arr.data()), m_end(arr.data() + arr.size()) { }
|
||||||
|
|
||||||
|
template <typename Cont> span(Cont &cont) : m_beg(std::data(cont)), m_end(std::data(cont) + std::size(cont)) { }
|
||||||
|
|
||||||
span(const span &other) : m_beg(other.begin()), m_end(other.end()) { }
|
span(const span &other) : m_beg(other.begin()), m_end(other.end()) { }
|
||||||
|
|
||||||
template <typename U> span(const span<U> &other) : m_beg(other.begin()), m_end(other.end()) { }
|
template <typename U> span(const span<U> &other) : m_beg(other.begin()), m_end(other.end()) { }
|
||||||
|
|
||||||
span & operator = (span other) { m_beg = other.begin(); m_end = other.end(); return *this; }
|
span & operator = (const span & other) noexcept = default;
|
||||||
|
|
||||||
iterator begin() const { return iterator(m_beg); }
|
iterator begin() const { return iterator(m_beg); }
|
||||||
iterator end() const { return iterator(m_end); }
|
iterator end() const { return iterator(m_end); }
|
||||||
|
|
||||||
|
@ -84,24 +100,26 @@ public:
|
||||||
|
|
||||||
operator bool () const noexcept { return m_beg != nullptr; }
|
operator bool () const noexcept { return m_beg != nullptr; }
|
||||||
|
|
||||||
reference operator[](size_type index) { return at(index); }
|
reference operator[](index_type index) { return at(index); }
|
||||||
const_reference operator[](size_type index) const { return at(index); }
|
const_reference operator[](index_type index) const { return at(index); }
|
||||||
|
|
||||||
bool operator==(span const & other) const noexcept { return size() == other.size() && (m_beg == other.m_beg || std::equal(begin(), end(), other.begin())); }
|
bool operator==(span const & other) const noexcept { return size() == other.size() && (m_beg == other.m_beg || std::equal(begin(), end(), other.begin())); }
|
||||||
bool operator!=(span const & other) const noexcept { return !(*this == other); }
|
bool operator!=(span const & other) const noexcept { return !(*this == other); }
|
||||||
|
|
||||||
reference at(size_type index) { return m_beg[index]; }
|
reference at(index_type index) { return m_beg[index]; }
|
||||||
const_reference at(size_type index) const { return m_beg[index]; }
|
const_reference at(index_type index) const { return m_beg[index]; }
|
||||||
|
|
||||||
pointer data() const noexcept { return m_beg; }
|
pointer data() const noexcept { return m_beg; }
|
||||||
|
|
||||||
bool empty() const noexcept { return size() == 0; }
|
bool empty() const noexcept { return size() == 0; }
|
||||||
|
|
||||||
size_type size() const noexcept { return static_cast<size_type>(std::distance(m_beg, m_end)); }
|
index_type size() const noexcept { return static_cast<index_type>(std::distance(m_beg, m_end)); }
|
||||||
size_type length() const noexcept { return size(); }
|
index_type length() const noexcept { return size(); }
|
||||||
|
|
||||||
}; // class span
|
}; // class span
|
||||||
|
|
||||||
|
#endif // C++20
|
||||||
|
|
||||||
template <typename T> inline span<T> as_span(T * beg, T * end) { return span<T>(beg, end); }
|
template <typename T> inline span<T> as_span(T * beg, T * end) { return span<T>(beg, end); }
|
||||||
|
|
||||||
template <typename T> inline span<T> as_span(T * data, std::size_t size) { return span<T>(data, size); }
|
template <typename T> inline span<T> as_span(T * data, std::size_t size) { return span<T>(data, size); }
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -19,6 +19,7 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
@ -47,9 +48,9 @@ template <typename Tstring>
|
||||||
struct string_traits
|
struct string_traits
|
||||||
{
|
{
|
||||||
|
|
||||||
typedef Tstring string_type;
|
using string_type = Tstring;
|
||||||
typedef typename string_type::size_type size_type;
|
using size_type = typename string_type::size_type;
|
||||||
typedef typename string_type::value_type char_type;
|
using char_type = typename string_type::value_type;
|
||||||
|
|
||||||
static inline std::size_t length(const string_type &str) { return str.length(); }
|
static inline std::size_t length(const string_type &str) { return str.length(); }
|
||||||
|
|
||||||
|
@ -68,14 +69,14 @@ struct string_traits
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(_MFC_VER)
|
#if defined(MPT_WITH_MFC)
|
||||||
template <>
|
template <>
|
||||||
struct string_traits<CString>
|
struct string_traits<CString>
|
||||||
{
|
{
|
||||||
|
|
||||||
typedef CString string_type;
|
using string_type = CString;
|
||||||
typedef int size_type;
|
using size_type = int;
|
||||||
typedef typename CString::XCHAR char_type;
|
using char_type = typename CString::XCHAR;
|
||||||
|
|
||||||
static inline size_type length(const string_type &str) { return str.GetLength(); }
|
static inline size_type length(const string_type &str) { return str.GetLength(); }
|
||||||
|
|
||||||
|
@ -94,7 +95,7 @@ struct string_traits<CString>
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif // MPT_WITH_MFC
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -178,54 +179,64 @@ inline Tstring Replace(Tstring str, const Tstring2 &oldStr_, const Tstring3 &new
|
||||||
} // namespace String
|
} // namespace String
|
||||||
|
|
||||||
|
|
||||||
static inline std::size_t strnlen(const char *str, std::size_t n)
|
static inline std::string truncate(std::string str, std::size_t maxLen)
|
||||||
{
|
{
|
||||||
#if MPT_COMPILER_MSVC
|
if(str.length() > maxLen)
|
||||||
return ::strnlen(str, n);
|
|
||||||
#else
|
|
||||||
if(n >= std::numeric_limits<std::size_t>::max())
|
|
||||||
{
|
{
|
||||||
return std::strlen(str);
|
str.resize(maxLen);
|
||||||
}
|
}
|
||||||
for(std::size_t i = 0; i < n; ++i)
|
return str;
|
||||||
{
|
|
||||||
if(str[i] == '\0')
|
|
||||||
{
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
enum Charset {
|
enum class Charset {
|
||||||
|
|
||||||
CharsetUTF8,
|
UTF8,
|
||||||
|
|
||||||
CharsetASCII, // strictly 7-bit ASCII
|
ASCII, // strictly 7-bit ASCII
|
||||||
|
|
||||||
CharsetISO8859_1,
|
ISO8859_1,
|
||||||
CharsetISO8859_15,
|
ISO8859_15,
|
||||||
|
|
||||||
CharsetCP437,
|
CP437,
|
||||||
CharsetCP437AMS,
|
CP437AMS,
|
||||||
CharsetCP437AMS2,
|
CP437AMS2,
|
||||||
|
|
||||||
CharsetWindows1252,
|
Windows1252,
|
||||||
|
|
||||||
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
||||||
CharsetLocale, // CP_ACP on windows, current C locale otherwise
|
Locale, // CP_ACP on windows, current C locale otherwise
|
||||||
#endif // MPT_ENABLE_CHARSET_LOCALE
|
#endif // MPT_ENABLE_CHARSET_LOCALE
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// source code / preprocessor (i.e. # token)
|
||||||
|
inline constexpr Charset CharsetSource = Charset::ASCII;
|
||||||
|
|
||||||
|
// debug log files
|
||||||
|
inline constexpr Charset CharsetLogfile = Charset::UTF8;
|
||||||
|
|
||||||
|
// std::clog / std::cout / std::cerr
|
||||||
|
#if defined(MODPLUG_TRACKER) && MPT_OS_WINDOWS && defined(MPT_ENABLE_CHARSET_LOCALE)
|
||||||
|
inline constexpr Charset CharsetStdIO = Charset::Locale;
|
||||||
|
#else
|
||||||
|
inline constexpr Charset CharsetStdIO = Charset::UTF8;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// std::exception::what()
|
||||||
|
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
||||||
|
inline constexpr Charset CharsetException = Charset::Locale;
|
||||||
|
#else
|
||||||
|
inline constexpr Charset CharsetException = Charset::UTF8;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Locale in tracker builds, UTF8 in non-locale-aware libopenmpt builds.
|
// Locale in tracker builds, UTF8 in non-locale-aware libopenmpt builds.
|
||||||
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
||||||
const Charset CharsetLocaleOrUTF8 = CharsetLocale;
|
inline constexpr Charset CharsetLocaleOrUTF8 = Charset::Locale;
|
||||||
#else
|
#else
|
||||||
const Charset CharsetLocaleOrUTF8 = CharsetUTF8;
|
inline constexpr Charset CharsetLocaleOrUTF8 = Charset::UTF8;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -267,30 +278,41 @@ struct charset_char_traits : std::char_traits<char> {
|
||||||
|
|
||||||
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
||||||
|
|
||||||
typedef MPT_ENCODED_STRING_TYPE(mpt::CharsetLocale) lstring;
|
using lstring = MPT_ENCODED_STRING_TYPE(mpt::Charset::Locale);
|
||||||
|
|
||||||
#endif // MPT_ENABLE_CHARSET_LOCALE
|
#endif // MPT_ENABLE_CHARSET_LOCALE
|
||||||
|
|
||||||
#if MPT_OS_WINDOWS
|
#if MPT_OS_WINDOWS
|
||||||
|
|
||||||
template <typename Tchar> struct windows_char_traits { };
|
template <typename Tchar> struct windows_char_traits { };
|
||||||
template <> struct windows_char_traits<char> { typedef mpt::lstring string_type; };
|
template <> struct windows_char_traits<char> { using string_type = mpt::lstring; };
|
||||||
template <> struct windows_char_traits<wchar_t> { typedef std::wstring string_type; };
|
template <> struct windows_char_traits<wchar_t> { using string_type = std::wstring; };
|
||||||
|
|
||||||
#ifdef UNICODE
|
#ifdef UNICODE
|
||||||
typedef windows_char_traits<wchar_t>::string_type tstring;
|
using tstring = windows_char_traits<wchar_t>::string_type;
|
||||||
#else
|
#else
|
||||||
typedef windows_char_traits<char>::string_type tstring;
|
using tstring = windows_char_traits<char>::string_type;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef mpt::tstring winstring;
|
using winstring = mpt::tstring;
|
||||||
|
|
||||||
#endif // MPT_OS_WINDOWS
|
#endif // MPT_OS_WINDOWS
|
||||||
|
|
||||||
|
|
||||||
#if MPT_ENABLE_U8STRING
|
#if MPT_ENABLE_U8STRING
|
||||||
|
|
||||||
typedef MPT_ENCODED_STRING_TYPE(mpt::CharsetUTF8) u8string;
|
#if MPT_CXX_AT_LEAST(20)
|
||||||
|
|
||||||
|
using u8string = std::u8string;
|
||||||
|
|
||||||
|
#define MPT_U8CHAR_TYPE char8_t
|
||||||
|
#define MPT_U8CHAR(x) u8 ## x
|
||||||
|
#define MPT_U8LITERAL(x) u8 ## x
|
||||||
|
#define MPT_U8STRING(x) std::u8string( u8 ## x )
|
||||||
|
|
||||||
|
#else // !C++20
|
||||||
|
|
||||||
|
using u8string = MPT_ENCODED_STRING_TYPE(mpt::Charset::UTF8);
|
||||||
|
|
||||||
#define MPT_U8CHAR_TYPE char
|
#define MPT_U8CHAR_TYPE char
|
||||||
#define MPT_U8CHAR(x) x
|
#define MPT_U8CHAR(x) x
|
||||||
|
@ -311,6 +333,8 @@ typedef MPT_ENCODED_STRING_TYPE(mpt::CharsetUTF8) u8string;
|
||||||
// mpt::u8string is meant as an alternative implementaion to std::wstring
|
// mpt::u8string is meant as an alternative implementaion to std::wstring
|
||||||
// for implementing the unicode string type mpt::ustring.
|
// for implementing the unicode string type mpt::ustring.
|
||||||
|
|
||||||
|
#endif // C++20
|
||||||
|
|
||||||
#endif // MPT_ENABLE_U8STRING
|
#endif // MPT_ENABLE_U8STRING
|
||||||
|
|
||||||
|
|
||||||
|
@ -367,7 +391,7 @@ mpt::winstring ToWin(const mpt::lstring &str);
|
||||||
#endif // MPT_OS_WINDOWS
|
#endif // MPT_OS_WINDOWS
|
||||||
|
|
||||||
|
|
||||||
#if defined(_MFC_VER)
|
#if defined(MPT_WITH_MFC)
|
||||||
#if !(MPT_WSTRING_CONVERT)
|
#if !(MPT_WSTRING_CONVERT)
|
||||||
#error "MFC depends on MPT_WSTRING_CONVERT)"
|
#error "MFC depends on MPT_WSTRING_CONVERT)"
|
||||||
#endif
|
#endif
|
||||||
|
@ -394,7 +418,7 @@ mpt::winstring ToWin(const CString &str);
|
||||||
std::wstring ToWide(const CString &str);
|
std::wstring ToWide(const CString &str);
|
||||||
std::string ToCharset(Charset to, const CString &str);
|
std::string ToCharset(Charset to, const CString &str);
|
||||||
|
|
||||||
#endif // MFC
|
#endif // MPT_WITH_MFC
|
||||||
|
|
||||||
|
|
||||||
// mpt::ustring
|
// mpt::ustring
|
||||||
|
@ -423,8 +447,8 @@ std::string ToCharset(Charset to, const CString &str);
|
||||||
#error "MPT_USTRING_MODE_WIDE and MPT_USTRING_MODE_UTF8 are mutually exclusive."
|
#error "MPT_USTRING_MODE_WIDE and MPT_USTRING_MODE_UTF8 are mutually exclusive."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef std::wstring ustring;
|
using ustring = std::wstring;
|
||||||
#define MPT_UCHAR_TYPE wchar_t
|
using uchar = wchar_t;
|
||||||
#define MPT_UCHAR(x) L ## x
|
#define MPT_UCHAR(x) L ## x
|
||||||
#define MPT_ULITERAL(x) L ## x
|
#define MPT_ULITERAL(x) L ## x
|
||||||
#define MPT_USTRING(x) std::wstring( L ## x )
|
#define MPT_USTRING(x) std::wstring( L ## x )
|
||||||
|
@ -436,11 +460,11 @@ typedef std::wstring ustring;
|
||||||
#error "MPT_USTRING_MODE_WIDE and MPT_USTRING_MODE_UTF8 are mutually exclusive."
|
#error "MPT_USTRING_MODE_WIDE and MPT_USTRING_MODE_UTF8 are mutually exclusive."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef mpt::u8string ustring;
|
using ustring = mpt::u8string;
|
||||||
#define MPT_UCHAR_TYPE char
|
using uchar = MPT_U8CHAR_TYPE;
|
||||||
#define MPT_UCHAR(x) x
|
#define MPT_UCHAR(x) MPT_U8CHAR( x )
|
||||||
#define MPT_ULITERAL(x) x
|
#define MPT_ULITERAL(x) MPT_U8LITERAL( x )
|
||||||
#define MPT_USTRING(x) mpt::ustring( x )
|
#define MPT_USTRING(x) MPT_U8STRING( x )
|
||||||
|
|
||||||
#endif // MPT_USTRING_MODE_UTF8
|
#endif // MPT_USTRING_MODE_UTF8
|
||||||
|
|
||||||
|
@ -459,7 +483,7 @@ static inline mpt::ustring ToUnicode(Charset from, const char * str) { return To
|
||||||
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
||||||
static inline mpt::ustring ToUnicode(const mpt::lstring &str) { return ToWide(str); }
|
static inline mpt::ustring ToUnicode(const mpt::lstring &str) { return ToWide(str); }
|
||||||
#endif // MPT_ENABLE_CHARSET_LOCALE
|
#endif // MPT_ENABLE_CHARSET_LOCALE
|
||||||
#if defined(_MFC_VER)
|
#if defined(MPT_WITH_MFC)
|
||||||
static inline mpt::ustring ToUnicode(const CString &str) { return ToWide(str); }
|
static inline mpt::ustring ToUnicode(const CString &str) { return ToWide(str); }
|
||||||
#endif // MFC
|
#endif // MFC
|
||||||
#else // !MPT_USTRING_MODE_WIDE
|
#else // !MPT_USTRING_MODE_WIDE
|
||||||
|
@ -473,9 +497,9 @@ static inline mpt::ustring ToUnicode(Charset from, const char * str) { return To
|
||||||
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
||||||
mpt::ustring ToUnicode(const mpt::lstring &str);
|
mpt::ustring ToUnicode(const mpt::lstring &str);
|
||||||
#endif // MPT_ENABLE_CHARSET_LOCALE
|
#endif // MPT_ENABLE_CHARSET_LOCALE
|
||||||
#if defined(_MFC_VER)
|
#if defined(MPT_WITH_MFC)
|
||||||
mpt::ustring ToUnicode(const CString &str);
|
mpt::ustring ToUnicode(const CString &str);
|
||||||
#endif // MFC
|
#endif // MPT_WITH_MFC
|
||||||
#endif // MPT_USTRING_MODE_WIDE
|
#endif // MPT_USTRING_MODE_WIDE
|
||||||
|
|
||||||
#if MPT_USTRING_MODE_WIDE
|
#if MPT_USTRING_MODE_WIDE
|
||||||
|
@ -494,9 +518,9 @@ mpt::lstring ToLocale(const mpt::ustring &str);
|
||||||
#if MPT_OS_WINDOWS
|
#if MPT_OS_WINDOWS
|
||||||
mpt::winstring ToWin(const mpt::ustring &str);
|
mpt::winstring ToWin(const mpt::ustring &str);
|
||||||
#endif // MPT_OS_WINDOWS
|
#endif // MPT_OS_WINDOWS
|
||||||
#if defined(_MFC_VER)
|
#if defined(MPT_WITH_MFC)
|
||||||
CString ToCString(const mpt::ustring &str);
|
CString ToCString(const mpt::ustring &str);
|
||||||
#endif // MFC
|
#endif // MPT_WITH_MFC
|
||||||
#endif // MPT_USTRING_MODE_WIDE
|
#endif // MPT_USTRING_MODE_WIDE
|
||||||
|
|
||||||
// The MPT_UTF8 allows specifying UTF8 char arrays.
|
// The MPT_UTF8 allows specifying UTF8 char arrays.
|
||||||
|
@ -504,7 +528,7 @@ CString ToCString(const mpt::ustring &str);
|
||||||
// i.e. it is NOT generally available at compile time.
|
// i.e. it is NOT generally available at compile time.
|
||||||
// Use explicit UTF8 encoding,
|
// Use explicit UTF8 encoding,
|
||||||
// i.e. U+00FC (LATIN SMALL LETTER U WITH DIAERESIS) would be written as "\xC3\xBC".
|
// i.e. U+00FC (LATIN SMALL LETTER U WITH DIAERESIS) would be written as "\xC3\xBC".
|
||||||
#define MPT_UTF8(x) mpt::ToUnicode(mpt::CharsetUTF8, x )
|
#define MPT_UTF8(x) mpt::ToUnicode(mpt::Charset::UTF8, x )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -522,8 +546,10 @@ std::string ToLowerCaseAscii(std::string s);
|
||||||
std::string ToUpperCaseAscii(std::string s);
|
std::string ToUpperCaseAscii(std::string s);
|
||||||
|
|
||||||
int CompareNoCaseAscii(const char *a, const char *b, std::size_t n);
|
int CompareNoCaseAscii(const char *a, const char *b, std::size_t n);
|
||||||
|
int CompareNoCaseAscii(std::string_view a, std::string_view b);
|
||||||
int CompareNoCaseAscii(const std::string &a, const std::string &b);
|
int CompareNoCaseAscii(const std::string &a, const std::string &b);
|
||||||
|
|
||||||
|
|
||||||
#if defined(MODPLUG_TRACKER)
|
#if defined(MODPLUG_TRACKER)
|
||||||
|
|
||||||
mpt::ustring ToLowerCase(const mpt::ustring &s);
|
mpt::ustring ToLowerCase(const mpt::ustring &s);
|
||||||
|
@ -548,7 +574,7 @@ mpt::ustring ToUpperCase(const mpt::ustring &s);
|
||||||
// Warning: These types will silently do charset conversions. Only use them when this can be tolerated.
|
// Warning: These types will silently do charset conversions. Only use them when this can be tolerated.
|
||||||
|
|
||||||
// BasicAnyString is convertable to mpt::ustring and constructable from any string at all.
|
// BasicAnyString is convertable to mpt::ustring and constructable from any string at all.
|
||||||
template <mpt::Charset charset = mpt::CharsetUTF8, bool tryUTF8 = true>
|
template <mpt::Charset charset = mpt::Charset::UTF8, bool tryUTF8 = true>
|
||||||
class BasicAnyString : public mpt::ustring
|
class BasicAnyString : public mpt::ustring
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -556,17 +582,17 @@ private:
|
||||||
|
|
||||||
static mpt::ustring From8bit(const std::string &str)
|
static mpt::ustring From8bit(const std::string &str)
|
||||||
{
|
{
|
||||||
MPT_CONSTANT_IF(charset == mpt::CharsetUTF8)
|
if constexpr(charset == mpt::Charset::UTF8)
|
||||||
{
|
{
|
||||||
return mpt::ToUnicode(mpt::CharsetUTF8, str);
|
return mpt::ToUnicode(mpt::Charset::UTF8, str);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
// auto utf8 detection
|
// auto utf8 detection
|
||||||
MPT_CONSTANT_IF(tryUTF8)
|
if constexpr(tryUTF8)
|
||||||
{
|
{
|
||||||
if(mpt::IsUTF8(str))
|
if(mpt::IsUTF8(str))
|
||||||
{
|
{
|
||||||
return mpt::ToUnicode(mpt::CharsetUTF8, str);
|
return mpt::ToUnicode(mpt::Charset::UTF8, str);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
return mpt::ToUnicode(charset, str);
|
return mpt::ToUnicode(charset, str);
|
||||||
|
@ -600,9 +626,9 @@ public:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// mfc
|
// mfc
|
||||||
#if defined(_MFC_VER)
|
#if defined(MPT_WITH_MFC)
|
||||||
BasicAnyString(const CString &str) : mpt::ustring(mpt::ToUnicode(str)) { }
|
BasicAnyString(const CString &str) : mpt::ustring(mpt::ToUnicode(str)) { }
|
||||||
#endif
|
#endif // MPT_WITH_MFC
|
||||||
|
|
||||||
// fallback for custom string types
|
// fallback for custom string types
|
||||||
template <typename Tstring> BasicAnyString(const Tstring &str) : mpt::ustring(mpt::ToUnicode(str)) { }
|
template <typename Tstring> BasicAnyString(const Tstring &str) : mpt::ustring(mpt::ToUnicode(str)) { }
|
||||||
|
@ -632,9 +658,9 @@ public:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// mfc
|
// mfc
|
||||||
#if defined(_MFC_VER)
|
#if defined(MPT_WITH_MFC)
|
||||||
AnyUnicodeString(const CString &str) : mpt::ustring(mpt::ToUnicode(str)) { }
|
AnyUnicodeString(const CString &str) : mpt::ustring(mpt::ToUnicode(str)) { }
|
||||||
#endif
|
#endif // MPT_WITH_MFC
|
||||||
|
|
||||||
// fallback for custom string types
|
// fallback for custom string types
|
||||||
template <typename Tstring> AnyUnicodeString(const Tstring &str) : mpt::ustring(mpt::ToUnicode(str)) { }
|
template <typename Tstring> AnyUnicodeString(const Tstring &str) : mpt::ustring(mpt::ToUnicode(str)) { }
|
||||||
|
@ -645,32 +671,32 @@ public:
|
||||||
// AnyString
|
// AnyString
|
||||||
// Try to do the smartest auto-magic we can do.
|
// Try to do the smartest auto-magic we can do.
|
||||||
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
||||||
typedef BasicAnyString<mpt::CharsetLocale, true> AnyString;
|
using AnyString = BasicAnyString<mpt::Charset::Locale, true>;
|
||||||
#elif MPT_OS_WINDOWS
|
#elif MPT_OS_WINDOWS
|
||||||
typedef BasicAnyString<mpt::CharsetWindows1252, true> AnyString;
|
using AnyString = BasicAnyString<mpt::Charset::Windows1252, true>;
|
||||||
#else
|
#else
|
||||||
typedef BasicAnyString<mpt::CharsetISO8859_1, true> AnyString;
|
using AnyString = BasicAnyString<mpt::Charset::ISO8859_1, true>;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// AnyStringLocale
|
// AnyStringLocale
|
||||||
// char-based strings are assumed to be in locale encoding.
|
// char-based strings are assumed to be in locale encoding.
|
||||||
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
||||||
typedef BasicAnyString<mpt::CharsetLocale, false> AnyStringLocale;
|
using AnyStringLocale = BasicAnyString<mpt::Charset::Locale, false>;
|
||||||
#else
|
#else
|
||||||
typedef BasicAnyString<mpt::CharsetUTF8, false> AnyStringLocale;
|
using AnyStringLocale = BasicAnyString<mpt::Charset::UTF8, false>;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// AnyStringUTF8orLocale
|
// AnyStringUTF8orLocale
|
||||||
// char-based strings are tried in UTF8 first, if this fails, locale is used.
|
// char-based strings are tried in UTF8 first, if this fails, locale is used.
|
||||||
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
||||||
typedef BasicAnyString<mpt::CharsetLocale, true> AnyStringUTF8orLocale;
|
using AnyStringUTF8orLocale = BasicAnyString<mpt::Charset::Locale, true>;
|
||||||
#else
|
#else
|
||||||
typedef BasicAnyString<mpt::CharsetUTF8, false> AnyStringUTF8orLocale;
|
using AnyStringUTF8orLocale = BasicAnyString<mpt::Charset::UTF8, false>;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// AnyStringUTF8
|
// AnyStringUTF8
|
||||||
// char-based strings are assumed to be in UTF8.
|
// char-based strings are assumed to be in UTF8.
|
||||||
typedef BasicAnyString<mpt::CharsetUTF8, false> AnyStringUTF8;
|
using AnyStringUTF8 = BasicAnyString<mpt::Charset::UTF8, false>;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
#include "BuildSettings.h"
|
#include "BuildSettings.h"
|
||||||
|
|
||||||
|
#include "mptMemory.h"
|
||||||
#include "mptString.h"
|
#include "mptString.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
@ -33,19 +34,19 @@ namespace String
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
enum ReadWriteMode
|
enum ReadWriteMode : uint8
|
||||||
{
|
{
|
||||||
// Reading / Writing: Standard null-terminated string handling.
|
// Reading / Writing: Standard null-terminated string handling.
|
||||||
nullTerminated,
|
nullTerminated = 1,
|
||||||
// Reading: Source string is not guaranteed to be null-terminated (if it fills the whole char array).
|
// Reading: Source string is not guaranteed to be null-terminated (if it fills the whole char array).
|
||||||
// Writing: Destination string is not guaranteed to be null-terminated (if it fills the whole char array).
|
// Writing: Destination string is not guaranteed to be null-terminated (if it fills the whole char array).
|
||||||
maybeNullTerminated,
|
maybeNullTerminated = 2,
|
||||||
// Reading: String may contain null characters anywhere. They should be treated as spaces.
|
// Reading: String may contain null characters anywhere. They should be treated as spaces.
|
||||||
// Writing: A space-padded string is written.
|
// Writing: A space-padded string is written.
|
||||||
spacePadded,
|
spacePadded = 3,
|
||||||
// Reading: String may contain null characters anywhere. The last character is ignored (it is supposed to be 0).
|
// Reading: String may contain null characters anywhere. The last character is ignored (it is supposed to be 0).
|
||||||
// Writing: A space-padded string with a trailing null is written.
|
// Writing: A space-padded string with a trailing null is written.
|
||||||
spacePaddedNull
|
spacePaddedNull = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
|
@ -75,7 +76,7 @@ public:
|
||||||
: buf(buf)
|
: buf(buf)
|
||||||
, size(size)
|
, size(size)
|
||||||
{
|
{
|
||||||
MPT_STATIC_ASSERT(sizeof(Tchar) == sizeof(typename Tstring::value_type));
|
static_assert(sizeof(Tchar) == sizeof(typename Tstring::value_type));
|
||||||
MPT_ASSERT(size > 0);
|
MPT_ASSERT(size > 0);
|
||||||
}
|
}
|
||||||
StringBufRefImpl(const StringBufRefImpl &) = delete;
|
StringBufRefImpl(const StringBufRefImpl &) = delete;
|
||||||
|
@ -87,6 +88,10 @@ public:
|
||||||
std::size_t len = std::find(buf, buf + size, Tchar('\0')) - buf; // terminate at \0
|
std::size_t len = std::find(buf, buf + size, Tchar('\0')) - buf; // terminate at \0
|
||||||
return Tstring(buf, buf + len);
|
return Tstring(buf, buf + len);
|
||||||
}
|
}
|
||||||
|
bool empty() const
|
||||||
|
{
|
||||||
|
return buf[0] == Tchar('\0');
|
||||||
|
}
|
||||||
StringBufRefImpl & operator = (const Tstring & str)
|
StringBufRefImpl & operator = (const Tstring & str)
|
||||||
{
|
{
|
||||||
std::fill(buf, buf + size, Tchar('\0'));
|
std::fill(buf, buf + size, Tchar('\0'));
|
||||||
|
@ -109,7 +114,7 @@ public:
|
||||||
: buf(buf)
|
: buf(buf)
|
||||||
, size(size)
|
, size(size)
|
||||||
{
|
{
|
||||||
MPT_STATIC_ASSERT(sizeof(Tchar) == sizeof(typename Tstring::value_type));
|
static_assert(sizeof(Tchar) == sizeof(typename Tstring::value_type));
|
||||||
MPT_ASSERT(size > 0);
|
MPT_ASSERT(size > 0);
|
||||||
}
|
}
|
||||||
StringBufRefImpl(const StringBufRefImpl &) = delete;
|
StringBufRefImpl(const StringBufRefImpl &) = delete;
|
||||||
|
@ -121,6 +126,10 @@ public:
|
||||||
std::size_t len = std::find(buf, buf + size, Tchar('\0')) - buf; // terminate at \0
|
std::size_t len = std::find(buf, buf + size, Tchar('\0')) - buf; // terminate at \0
|
||||||
return Tstring(buf, buf + len);
|
return Tstring(buf, buf + len);
|
||||||
}
|
}
|
||||||
|
bool empty() const
|
||||||
|
{
|
||||||
|
return buf[0] == Tchar('\0');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace String {
|
namespace String {
|
||||||
|
@ -169,6 +178,49 @@ inline StringBufRefImpl<typename std::basic_string<typename std::remove_const<Tc
|
||||||
}
|
}
|
||||||
} // namespace String
|
} // namespace String
|
||||||
|
|
||||||
|
template <std::size_t len, mpt::String::ReadWriteMode mode = static_cast<mpt::String::ReadWriteMode>(0)> struct charbuf;
|
||||||
|
|
||||||
|
template <std::size_t len>
|
||||||
|
struct charbuf<len, static_cast<mpt::String::ReadWriteMode>(0)>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef char Tchar;
|
||||||
|
using char_type = Tchar;
|
||||||
|
using string_type = std::basic_string<Tchar>;
|
||||||
|
constexpr std::size_t static_length() const { return len; }
|
||||||
|
public:
|
||||||
|
Tchar buf[len];
|
||||||
|
public:
|
||||||
|
charbuf()
|
||||||
|
{
|
||||||
|
Clear(buf);
|
||||||
|
}
|
||||||
|
charbuf(const charbuf &) = default;
|
||||||
|
charbuf(charbuf &&) = default;
|
||||||
|
charbuf & operator = (const charbuf &) = default;
|
||||||
|
charbuf & operator = (charbuf &&) = default;
|
||||||
|
const Tchar & operator[](std::size_t i) const { return buf[i]; }
|
||||||
|
std::string str() const { return static_cast<std::string>(*this); }
|
||||||
|
operator string_type () const
|
||||||
|
{
|
||||||
|
return mpt::String::ReadAutoBuf(buf);
|
||||||
|
}
|
||||||
|
bool empty() const
|
||||||
|
{
|
||||||
|
return mpt::String::ReadAutoBuf(buf).empty();
|
||||||
|
}
|
||||||
|
charbuf & operator = (const string_type & str)
|
||||||
|
{
|
||||||
|
mpt::String::WriteAutoBuf(buf) = str;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
friend bool operator!=(const std::string & a, const charbuf & b) { return a != b.str(); }
|
||||||
|
friend bool operator!=(const charbuf & a, const std::string & b) { return a.str() != b; }
|
||||||
|
friend bool operator==(const std::string & a, const charbuf & b) { return a == b.str(); }
|
||||||
|
friend bool operator==(const charbuf & a, const std::string & b) { return a.str() == b; }
|
||||||
|
};
|
||||||
|
|
||||||
template <typename Tchar>
|
template <typename Tchar>
|
||||||
class StringModeBufRefImpl
|
class StringModeBufRefImpl
|
||||||
{
|
{
|
||||||
|
@ -184,7 +236,7 @@ public:
|
||||||
, size(size)
|
, size(size)
|
||||||
, mode(mode)
|
, mode(mode)
|
||||||
{
|
{
|
||||||
MPT_STATIC_ASSERT(sizeof(Tchar) == 1);
|
static_assert(sizeof(Tchar) == 1);
|
||||||
}
|
}
|
||||||
StringModeBufRefImpl(const StringModeBufRefImpl &) = delete;
|
StringModeBufRefImpl(const StringModeBufRefImpl &) = delete;
|
||||||
StringModeBufRefImpl(StringModeBufRefImpl &&) = default;
|
StringModeBufRefImpl(StringModeBufRefImpl &&) = default;
|
||||||
|
@ -194,6 +246,10 @@ public:
|
||||||
{
|
{
|
||||||
return String::detail::ReadStringBuffer(mode, buf, size);
|
return String::detail::ReadStringBuffer(mode, buf, size);
|
||||||
}
|
}
|
||||||
|
bool empty() const
|
||||||
|
{
|
||||||
|
return String::detail::ReadStringBuffer(mode, buf, size).empty();
|
||||||
|
}
|
||||||
StringModeBufRefImpl & operator = (const std::string & str)
|
StringModeBufRefImpl & operator = (const std::string & str)
|
||||||
{
|
{
|
||||||
String::detail::WriteStringBuffer(mode, buf, size, str.data(), str.size());
|
String::detail::WriteStringBuffer(mode, buf, size, str.data(), str.size());
|
||||||
|
@ -216,7 +272,7 @@ public:
|
||||||
, size(size)
|
, size(size)
|
||||||
, mode(mode)
|
, mode(mode)
|
||||||
{
|
{
|
||||||
MPT_STATIC_ASSERT(sizeof(Tchar) == 1);
|
static_assert(sizeof(Tchar) == 1);
|
||||||
}
|
}
|
||||||
StringModeBufRefImpl(const StringModeBufRefImpl &) = delete;
|
StringModeBufRefImpl(const StringModeBufRefImpl &) = delete;
|
||||||
StringModeBufRefImpl(StringModeBufRefImpl &&) = default;
|
StringModeBufRefImpl(StringModeBufRefImpl &&) = default;
|
||||||
|
@ -226,6 +282,10 @@ public:
|
||||||
{
|
{
|
||||||
return String::detail::ReadStringBuffer(mode, buf, size);
|
return String::detail::ReadStringBuffer(mode, buf, size);
|
||||||
}
|
}
|
||||||
|
bool empty() const
|
||||||
|
{
|
||||||
|
return String::detail::ReadStringBuffer(mode, buf, size).empty();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace String {
|
namespace String {
|
||||||
|
@ -251,6 +311,46 @@ inline StringModeBufRefImpl<Tchar> WriteBuf(String::ReadWriteMode mode, Tchar *
|
||||||
}
|
}
|
||||||
} // namespace String
|
} // namespace String
|
||||||
|
|
||||||
|
template <std::size_t len, mpt::String::ReadWriteMode mode>
|
||||||
|
struct charbuf
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef char Tchar;
|
||||||
|
using char_type = Tchar;
|
||||||
|
using string_type = std::basic_string<Tchar>;
|
||||||
|
public:
|
||||||
|
Tchar buf[len];
|
||||||
|
public:
|
||||||
|
charbuf() = default;
|
||||||
|
charbuf(const charbuf &) = default;
|
||||||
|
charbuf(charbuf &&) = default;
|
||||||
|
charbuf & operator = (const charbuf &) = default;
|
||||||
|
charbuf & operator = (charbuf &&) = default;
|
||||||
|
operator string_type () const
|
||||||
|
{
|
||||||
|
return mpt::String::ReadBuf(mode, buf);
|
||||||
|
}
|
||||||
|
bool empty() const
|
||||||
|
{
|
||||||
|
return mpt::String::ReadBuf(mode, buf).empty();
|
||||||
|
}
|
||||||
|
charbuf & operator = (const string_type & str)
|
||||||
|
{
|
||||||
|
mpt::String::WriteBuf(mode, buf) = str;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// see MPT_BINARY_STRUCT
|
||||||
|
template <std::size_t len, mpt::String::ReadWriteMode mode>
|
||||||
|
struct is_binary_safe<typename mpt::charbuf<len, mode>> : public std::true_type { };
|
||||||
|
template <std::size_t len>
|
||||||
|
struct is_binary_safe<typename mpt::charbuf<len, static_cast<mpt::String::ReadWriteMode>(0)>> : public std::false_type { };
|
||||||
|
static_assert(sizeof(mpt::charbuf<7>) == 7);
|
||||||
|
static_assert(alignof(mpt::charbuf<7>) == 1);
|
||||||
|
static_assert(std::is_standard_layout<mpt::charbuf<7>>::value);
|
||||||
|
|
||||||
|
|
||||||
#ifdef MODPLUG_TRACKER
|
#ifdef MODPLUG_TRACKER
|
||||||
|
|
||||||
|
@ -279,7 +379,7 @@ inline StringBufRefImpl<typename mpt::windows_char_traits<typename std::remove_c
|
||||||
}
|
}
|
||||||
} // namespace String
|
} // namespace String
|
||||||
|
|
||||||
#if defined(_MFC_VER)
|
#if defined(MPT_WITH_MFC)
|
||||||
|
|
||||||
template <typename Tchar>
|
template <typename Tchar>
|
||||||
class CStringBufRefImpl
|
class CStringBufRefImpl
|
||||||
|
@ -363,7 +463,7 @@ inline CStringBufRefImpl<Tchar> WriteCStringBuf(Tchar * buf, std::size_t size)
|
||||||
}
|
}
|
||||||
} // namespace String
|
} // namespace String
|
||||||
|
|
||||||
#endif // _MFC_VER
|
#endif // MPT_WITH_MFC
|
||||||
|
|
||||||
#endif // MPT_OS_WINDOWS
|
#endif // MPT_OS_WINDOWS
|
||||||
|
|
||||||
|
@ -388,7 +488,7 @@ namespace String
|
||||||
template <size_t size>
|
template <size_t size>
|
||||||
void SetNullTerminator(char (&buffer)[size])
|
void SetNullTerminator(char (&buffer)[size])
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(size > 0);
|
static_assert(size > 0);
|
||||||
buffer[size - 1] = 0;
|
buffer[size - 1] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,7 +503,7 @@ namespace String
|
||||||
template <size_t size>
|
template <size_t size>
|
||||||
void SetNullTerminator(wchar_t (&buffer)[size])
|
void SetNullTerminator(wchar_t (&buffer)[size])
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(size > 0);
|
static_assert(size > 0);
|
||||||
buffer[size - 1] = 0;
|
buffer[size - 1] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -420,7 +520,7 @@ namespace String
|
||||||
template <size_t size>
|
template <size_t size>
|
||||||
void FixNullString(char (&buffer)[size])
|
void FixNullString(char (&buffer)[size])
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(size > 0);
|
static_assert(size > 0);
|
||||||
SetNullTerminator(buffer);
|
SetNullTerminator(buffer);
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
// Find the first null char.
|
// Find the first null char.
|
||||||
|
@ -449,244 +549,6 @@ namespace String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Copy a string from srcBuffer to destBuffer using a given read mode.
|
|
||||||
// Used for reading strings from files.
|
|
||||||
// Only use this version of the function if the size of the source buffer is variable.
|
|
||||||
template <ReadWriteMode mode, typename Tbyte>
|
|
||||||
void Read(std::string &dest, const Tbyte *srcBuffer, size_t srcSize)
|
|
||||||
{
|
|
||||||
|
|
||||||
const char *src = mpt::byte_cast<const char*>(srcBuffer);
|
|
||||||
|
|
||||||
dest.clear();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
dest = mpt::String::detail::ReadStringBuffer(mode, src, srcSize);
|
|
||||||
} MPT_EXCEPTION_CATCH_OUT_OF_MEMORY(e)
|
|
||||||
{
|
|
||||||
MPT_EXCEPTION_DELETE_OUT_OF_MEMORY(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy a charset encoded string from srcBuffer to destBuffer using a given read mode.
|
|
||||||
// Used for reading strings from files.
|
|
||||||
// Only use this version of the function if the size of the source buffer is variable.
|
|
||||||
template <ReadWriteMode mode, typename Tbyte>
|
|
||||||
void Read(mpt::ustring &dest, mpt::Charset charset, const Tbyte *srcBuffer, size_t srcSize)
|
|
||||||
{
|
|
||||||
std::string tmp;
|
|
||||||
Read<mode>(tmp, srcBuffer, srcSize);
|
|
||||||
dest = mpt::ToUnicode(charset, tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Used for reading strings from files.
|
|
||||||
// Preferrably use this version of the function, it is safer.
|
|
||||||
template <ReadWriteMode mode, size_t srcSize, typename Tbyte>
|
|
||||||
void Read(std::string &dest, const Tbyte (&srcBuffer)[srcSize])
|
|
||||||
{
|
|
||||||
STATIC_ASSERT(srcSize > 0);
|
|
||||||
Read<mode>(dest, srcBuffer, srcSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Used for reading charset encoded strings from files.
|
|
||||||
// Preferrably use this version of the function, it is safer.
|
|
||||||
template <ReadWriteMode mode, size_t srcSize, typename Tbyte>
|
|
||||||
void Read(mpt::ustring &dest, mpt::Charset charset, const Tbyte(&srcBuffer)[srcSize])
|
|
||||||
{
|
|
||||||
std::string tmp;
|
|
||||||
Read<mode>(tmp, srcBuffer);
|
|
||||||
dest = mpt::ToUnicode(charset, tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy a string from srcBuffer to destBuffer using a given read mode.
|
|
||||||
// Used for reading strings from files.
|
|
||||||
// Only use this version of the function if the size of the source buffer is variable.
|
|
||||||
template <ReadWriteMode mode, size_t destSize, typename Tbyte>
|
|
||||||
void Read(char (&destBuffer)[destSize], const Tbyte *srcBuffer, size_t srcSize)
|
|
||||||
{
|
|
||||||
STATIC_ASSERT(destSize > 0);
|
|
||||||
|
|
||||||
char *dst = destBuffer;
|
|
||||||
const char *src = mpt::byte_cast<const char*>(srcBuffer);
|
|
||||||
|
|
||||||
if(mode == nullTerminated || mode == spacePaddedNull)
|
|
||||||
{
|
|
||||||
// We assume that the last character of the source buffer is null.
|
|
||||||
if(srcSize > 0)
|
|
||||||
{
|
|
||||||
srcSize -= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mode == nullTerminated || mode == maybeNullTerminated)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Copy string and leave one character space in the destination buffer for null.
|
|
||||||
dst = std::copy(src, std::find(src, src + std::min(srcSize, destSize - 1), '\0'), dst);
|
|
||||||
|
|
||||||
} else if(mode == spacePadded || mode == spacePaddedNull)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Copy string and leave one character space in the destination buffer for null.
|
|
||||||
// Convert nulls to spaces while copying and counts the length that contains actual characters.
|
|
||||||
std::size_t lengthWithoutNullOrSpace = 0;
|
|
||||||
for(std::size_t pos = 0; pos < srcSize; ++pos)
|
|
||||||
{
|
|
||||||
char c = srcBuffer[pos];
|
|
||||||
if(c != '\0' && c != ' ')
|
|
||||||
{
|
|
||||||
lengthWithoutNullOrSpace = pos + 1;
|
|
||||||
}
|
|
||||||
if(c == '\0')
|
|
||||||
{
|
|
||||||
c = ' ';
|
|
||||||
}
|
|
||||||
if(pos < destSize - 1)
|
|
||||||
{
|
|
||||||
destBuffer[pos] = c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t destLength = std::min(lengthWithoutNullOrSpace, destSize - 1);
|
|
||||||
|
|
||||||
dst += destLength;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill rest of string with nulls.
|
|
||||||
std::fill(dst, destBuffer + destSize, '\0');
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Used for reading strings from files.
|
|
||||||
// Preferrably use this version of the function, it is safer.
|
|
||||||
template <ReadWriteMode mode, size_t destSize, size_t srcSize, typename Tbyte>
|
|
||||||
void Read(char (&destBuffer)[destSize], const Tbyte (&srcBuffer)[srcSize])
|
|
||||||
{
|
|
||||||
STATIC_ASSERT(destSize > 0);
|
|
||||||
STATIC_ASSERT(srcSize > 0);
|
|
||||||
Read<mode, destSize>(destBuffer, srcBuffer, srcSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Copy a string from srcBuffer to destBuffer using a given write mode.
|
|
||||||
// You should only use this function if src and dest are dynamically sized,
|
|
||||||
// otherwise use one of the safer overloads below.
|
|
||||||
template <ReadWriteMode mode>
|
|
||||||
void Write(char *destBuffer, const size_t destSize, const char *srcBuffer, const size_t srcSize)
|
|
||||||
{
|
|
||||||
MPT_ASSERT(destSize > 0);
|
|
||||||
|
|
||||||
mpt::String::detail::WriteStringBuffer(mode, destBuffer, destSize, srcBuffer, srcSize);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy a string from srcBuffer to a dynamically sized std::vector destBuffer using a given write mode.
|
|
||||||
// Used for writing strings to files.
|
|
||||||
// Only use this version of the function if the size of the source buffer is variable and the destination buffer also has variable size.
|
|
||||||
template <ReadWriteMode mode>
|
|
||||||
void Write(std::vector<char> &destBuffer, const char *srcBuffer, const size_t srcSize)
|
|
||||||
{
|
|
||||||
MPT_ASSERT(destBuffer.size() > 0);
|
|
||||||
Write<mode>(destBuffer.data(), destBuffer.size(), srcBuffer, srcSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy a string from srcBuffer to destBuffer using a given write mode.
|
|
||||||
// Used for writing strings to files.
|
|
||||||
// Only use this version of the function if the size of the source buffer is variable.
|
|
||||||
template <ReadWriteMode mode, size_t destSize>
|
|
||||||
void Write(char (&destBuffer)[destSize], const char *srcBuffer, const size_t srcSize)
|
|
||||||
{
|
|
||||||
STATIC_ASSERT(destSize > 0);
|
|
||||||
Write<mode>(destBuffer, destSize, srcBuffer, srcSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy a string from srcBuffer to destBuffer using a given write mode.
|
|
||||||
// Used for writing strings to files.
|
|
||||||
// Preferrably use this version of the function, it is safer.
|
|
||||||
template <ReadWriteMode mode, size_t destSize, size_t srcSize>
|
|
||||||
void Write(char (&destBuffer)[destSize], const char (&srcBuffer)[srcSize])
|
|
||||||
{
|
|
||||||
STATIC_ASSERT(destSize > 0);
|
|
||||||
STATIC_ASSERT(srcSize > 0);
|
|
||||||
Write<mode, destSize>(destBuffer, srcBuffer, srcSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <ReadWriteMode mode>
|
|
||||||
void Write(char *destBuffer, const size_t destSize, const std::string &src)
|
|
||||||
{
|
|
||||||
MPT_ASSERT(destSize > 0);
|
|
||||||
Write<mode>(destBuffer, destSize, src.c_str(), src.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <ReadWriteMode mode>
|
|
||||||
void Write(std::vector<char> &destBuffer, const std::string &src)
|
|
||||||
{
|
|
||||||
MPT_ASSERT(destBuffer.size() > 0);
|
|
||||||
Write<mode>(destBuffer, src.c_str(), src.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <ReadWriteMode mode, size_t destSize>
|
|
||||||
void Write(char (&destBuffer)[destSize], const std::string &src)
|
|
||||||
{
|
|
||||||
STATIC_ASSERT(destSize > 0);
|
|
||||||
Write<mode, destSize>(destBuffer, src.c_str(), src.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if MPT_GCC_AT_LEAST(8,1,0)
|
|
||||||
#pragma GCC diagnostic push
|
|
||||||
#pragma GCC diagnostic ignored "-Wstringop-truncation"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Copy from a char array to a fixed size char array.
|
|
||||||
template <size_t destSize>
|
|
||||||
void CopyN(char (&destBuffer)[destSize], const char *srcBuffer, const size_t srcSize = std::numeric_limits<size_t>::max())
|
|
||||||
{
|
|
||||||
const size_t copySize = std::min(destSize - 1u, srcSize);
|
|
||||||
std::strncpy(destBuffer, srcBuffer, copySize);
|
|
||||||
destBuffer[copySize] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy at most srcSize characters from srcBuffer to a std::string.
|
|
||||||
static inline void CopyN(std::string &dest, const char *srcBuffer, const size_t srcSize = std::numeric_limits<size_t>::max())
|
|
||||||
{
|
|
||||||
dest.assign(srcBuffer, srcBuffer + mpt::strnlen(srcBuffer, srcSize));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Copy from one fixed size char array to another one.
|
|
||||||
template <size_t destSize, size_t srcSize>
|
|
||||||
void Copy(char (&destBuffer)[destSize], const char (&srcBuffer)[srcSize])
|
|
||||||
{
|
|
||||||
CopyN(destBuffer, srcBuffer, srcSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy from a std::string to a fixed size char array.
|
|
||||||
template <size_t destSize>
|
|
||||||
void Copy(char (&destBuffer)[destSize], const std::string &src)
|
|
||||||
{
|
|
||||||
CopyN(destBuffer, src.c_str(), src.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy from a fixed size char array to a std::string.
|
|
||||||
template <size_t srcSize>
|
|
||||||
void Copy(std::string &dest, const char (&srcBuffer)[srcSize])
|
|
||||||
{
|
|
||||||
CopyN(dest, srcBuffer, srcSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy from a std::string to a std::string.
|
|
||||||
static inline void Copy(std::string &dest, const std::string &src)
|
|
||||||
{
|
|
||||||
dest.assign(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if MPT_GCC_AT_LEAST(8,1,0)
|
|
||||||
#pragma GCC diagnostic pop
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if MPT_COMPILER_MSVC
|
#if MPT_COMPILER_MSVC
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "mptStringFormat.h"
|
#include "mptStringFormat.h"
|
||||||
|
|
||||||
#if MPT_CXX_AT_LEAST(17) && MPT_COMPILER_MSVC
|
#if MPT_COMPILER_MSVC
|
||||||
#define MPT_FORMAT_CXX17_INT 1
|
#define MPT_FORMAT_CXX17_INT 1
|
||||||
#else
|
#else
|
||||||
#define MPT_FORMAT_CXX17_INT 0
|
#define MPT_FORMAT_CXX17_INT 0
|
||||||
|
@ -59,7 +59,7 @@ template<typename Tstream> inline void SaneInsert(Tstream & s, const unsigned ch
|
||||||
#if MPT_FORMAT_CXX17_INT
|
#if MPT_FORMAT_CXX17_INT
|
||||||
|
|
||||||
#if MPT_WSTRING_FORMAT
|
#if MPT_WSTRING_FORMAT
|
||||||
std::wstring ToWideSimple(const std::string &nstr)
|
static std::wstring ToWideSimple(const std::string &nstr)
|
||||||
{
|
{
|
||||||
std::wstring wstr(nstr.size(), L'\0');
|
std::wstring wstr(nstr.size(), L'\0');
|
||||||
for(std::size_t i = 0; i < nstr.size(); ++i)
|
for(std::size_t i = 0; i < nstr.size(); ++i)
|
||||||
|
@ -148,17 +148,6 @@ static inline std::wstring ToWStringHelperFloat(const T & x)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MPT_WSTRING_CONVERT
|
|
||||||
std::string ToString(const std::wstring & x) { return mpt::ToCharset(mpt::CharsetLocaleOrUTF8, x); }
|
|
||||||
std::string ToString(const wchar_t * const & x) { return mpt::ToCharset(mpt::CharsetLocaleOrUTF8, x); }
|
|
||||||
std::string ToString(const wchar_t & x) { return mpt::ToCharset(mpt::CharsetLocaleOrUTF8, std::wstring(1, x)); }
|
|
||||||
#endif
|
|
||||||
#if MPT_USTRING_MODE_UTF8
|
|
||||||
std::string ToString(const mpt::ustring & x) { return mpt::ToCharset(mpt::CharsetLocaleOrUTF8, x); }
|
|
||||||
#endif
|
|
||||||
#if defined(_MFC_VER)
|
|
||||||
std::string ToString(const CString & x) { return mpt::ToCharset(mpt::CharsetLocaleOrUTF8, x); }
|
|
||||||
#endif
|
|
||||||
std::string ToString(const bool & x) { return ToStringHelperInt(static_cast<int>(x)); }
|
std::string ToString(const bool & x) { return ToStringHelperInt(static_cast<int>(x)); }
|
||||||
std::string ToString(const signed char & x) { return ToStringHelperInt(x); }
|
std::string ToString(const signed char & x) { return ToStringHelperInt(x); }
|
||||||
std::string ToString(const unsigned char & x) { return ToStringHelperInt(x); }
|
std::string ToString(const unsigned char & x) { return ToStringHelperInt(x); }
|
||||||
|
@ -174,19 +163,15 @@ std::string ToString(const float & x) { return ToStringHelperFloat(x); }
|
||||||
std::string ToString(const double & x) { return ToStringHelperFloat(x); }
|
std::string ToString(const double & x) { return ToStringHelperFloat(x); }
|
||||||
std::string ToString(const long double & x) { return ToStringHelperFloat(x); }
|
std::string ToString(const long double & x) { return ToStringHelperFloat(x); }
|
||||||
|
|
||||||
mpt::ustring ToUString(const std::string & x) { return mpt::ToUnicode(mpt::CharsetLocaleOrUTF8, x); }
|
|
||||||
mpt::ustring ToUString(const char * const & x) { return mpt::ToUnicode(mpt::CharsetLocaleOrUTF8, x); }
|
|
||||||
mpt::ustring ToUString(const char & x) { return mpt::ToUnicode(mpt::CharsetLocaleOrUTF8, std::string(1, x)); }
|
|
||||||
#if MPT_WSTRING_FORMAT
|
#if MPT_WSTRING_FORMAT
|
||||||
#if MPT_USTRING_MODE_UTF8
|
#if MPT_USTRING_MODE_UTF8
|
||||||
mpt::ustring ToUString(const std::wstring & x) { return mpt::ToUnicode(x); }
|
mpt::ustring ToUString(const std::wstring & x) { return mpt::ToUnicode(x); }
|
||||||
#endif
|
#endif
|
||||||
mpt::ustring ToUString(const wchar_t * const & x) { return mpt::ToUnicode(x); }
|
mpt::ustring ToUString(const wchar_t * const & x) { return mpt::ToUnicode(x); }
|
||||||
mpt::ustring ToUString(const wchar_t & x) { return mpt::ToUnicode(std::wstring(1, x)); }
|
|
||||||
#endif
|
#endif
|
||||||
#if defined(_MFC_VER)
|
#if defined(MPT_WITH_MFC)
|
||||||
mpt::ustring ToUString(const CString & x) { return mpt::ToUnicode(x); }
|
mpt::ustring ToUString(const CString & x) { return mpt::ToUnicode(x); }
|
||||||
#endif
|
#endif // MPT_WITH_MFC
|
||||||
#if MPT_USTRING_MODE_WIDE
|
#if MPT_USTRING_MODE_WIDE
|
||||||
mpt::ustring ToUString(const bool & x) { return ToWStringHelperInt(static_cast<int>(x)); }
|
mpt::ustring ToUString(const bool & x) { return ToWStringHelperInt(static_cast<int>(x)); }
|
||||||
mpt::ustring ToUString(const signed char & x) { return ToWStringHelperInt(x); }
|
mpt::ustring ToUString(const signed char & x) { return ToWStringHelperInt(x); }
|
||||||
|
@ -204,32 +189,29 @@ mpt::ustring ToUString(const double & x) { return ToWStringHelperFloat(x); }
|
||||||
mpt::ustring ToUString(const long double & x) { return ToWStringHelperFloat(x); }
|
mpt::ustring ToUString(const long double & x) { return ToWStringHelperFloat(x); }
|
||||||
#endif
|
#endif
|
||||||
#if MPT_USTRING_MODE_UTF8
|
#if MPT_USTRING_MODE_UTF8
|
||||||
mpt::ustring ToUString(const bool & x) { return mpt::ToUnicode(mpt::CharsetUTF8, ToStringHelperInt(static_cast<int>(x))); }
|
mpt::ustring ToUString(const bool & x) { return mpt::ToUnicode(mpt::Charset::UTF8, ToStringHelperInt(static_cast<int>(x))); }
|
||||||
mpt::ustring ToUString(const signed char & x) { return mpt::ToUnicode(mpt::CharsetUTF8, ToStringHelperInt(x)); }
|
mpt::ustring ToUString(const signed char & x) { return mpt::ToUnicode(mpt::Charset::UTF8, ToStringHelperInt(x)); }
|
||||||
mpt::ustring ToUString(const unsigned char & x) { return mpt::ToUnicode(mpt::CharsetUTF8, ToStringHelperInt(x)); }
|
mpt::ustring ToUString(const unsigned char & x) { return mpt::ToUnicode(mpt::Charset::UTF8, ToStringHelperInt(x)); }
|
||||||
mpt::ustring ToUString(const signed short & x) { return mpt::ToUnicode(mpt::CharsetUTF8, ToStringHelperInt(x)); }
|
mpt::ustring ToUString(const signed short & x) { return mpt::ToUnicode(mpt::Charset::UTF8, ToStringHelperInt(x)); }
|
||||||
mpt::ustring ToUString(const unsigned short & x) { return mpt::ToUnicode(mpt::CharsetUTF8, ToStringHelperInt(x)); }
|
mpt::ustring ToUString(const unsigned short & x) { return mpt::ToUnicode(mpt::Charset::UTF8, ToStringHelperInt(x)); }
|
||||||
mpt::ustring ToUString(const signed int & x) { return mpt::ToUnicode(mpt::CharsetUTF8, ToStringHelperInt(x)); }
|
mpt::ustring ToUString(const signed int & x) { return mpt::ToUnicode(mpt::Charset::UTF8, ToStringHelperInt(x)); }
|
||||||
mpt::ustring ToUString(const unsigned int & x) { return mpt::ToUnicode(mpt::CharsetUTF8, ToStringHelperInt(x)); }
|
mpt::ustring ToUString(const unsigned int & x) { return mpt::ToUnicode(mpt::Charset::UTF8, ToStringHelperInt(x)); }
|
||||||
mpt::ustring ToUString(const signed long & x) { return mpt::ToUnicode(mpt::CharsetUTF8, ToStringHelperInt(x)); }
|
mpt::ustring ToUString(const signed long & x) { return mpt::ToUnicode(mpt::Charset::UTF8, ToStringHelperInt(x)); }
|
||||||
mpt::ustring ToUString(const unsigned long & x) { return mpt::ToUnicode(mpt::CharsetUTF8, ToStringHelperInt(x)); }
|
mpt::ustring ToUString(const unsigned long & x) { return mpt::ToUnicode(mpt::Charset::UTF8, ToStringHelperInt(x)); }
|
||||||
mpt::ustring ToUString(const signed long long & x) { return mpt::ToUnicode(mpt::CharsetUTF8, ToStringHelperInt(x)); }
|
mpt::ustring ToUString(const signed long long & x) { return mpt::ToUnicode(mpt::Charset::UTF8, ToStringHelperInt(x)); }
|
||||||
mpt::ustring ToUString(const unsigned long long & x) { return mpt::ToUnicode(mpt::CharsetUTF8, ToStringHelperInt(x)); }
|
mpt::ustring ToUString(const unsigned long long & x) { return mpt::ToUnicode(mpt::Charset::UTF8, ToStringHelperInt(x)); }
|
||||||
mpt::ustring ToUString(const float & x) { return mpt::ToUnicode(mpt::CharsetUTF8, ToStringHelperFloat(x)); }
|
mpt::ustring ToUString(const float & x) { return mpt::ToUnicode(mpt::Charset::UTF8, ToStringHelperFloat(x)); }
|
||||||
mpt::ustring ToUString(const double & x) { return mpt::ToUnicode(mpt::CharsetUTF8, ToStringHelperFloat(x)); }
|
mpt::ustring ToUString(const double & x) { return mpt::ToUnicode(mpt::Charset::UTF8, ToStringHelperFloat(x)); }
|
||||||
mpt::ustring ToUString(const long double & x) { return mpt::ToUnicode(mpt::CharsetUTF8, ToStringHelperFloat(x)); }
|
mpt::ustring ToUString(const long double & x) { return mpt::ToUnicode(mpt::Charset::UTF8, ToStringHelperFloat(x)); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MPT_WSTRING_FORMAT
|
#if MPT_WSTRING_FORMAT
|
||||||
std::wstring ToWString(const std::string & x) { return mpt::ToWide(mpt::CharsetLocaleOrUTF8, x); }
|
|
||||||
std::wstring ToWString(const char * const & x) { return mpt::ToWide(mpt::CharsetLocaleOrUTF8, x); }
|
|
||||||
std::wstring ToWString(const char & x) { return mpt::ToWide(mpt::CharsetLocaleOrUTF8, std::string(1, x)); }
|
|
||||||
#if MPT_USTRING_MODE_UTF8
|
#if MPT_USTRING_MODE_UTF8
|
||||||
std::wstring ToWString(const mpt::ustring & x) { return mpt::ToWide(x); }
|
std::wstring ToWString(const mpt::ustring & x) { return mpt::ToWide(x); }
|
||||||
#endif
|
#endif
|
||||||
#if defined(_MFC_VER)
|
#if defined(MPT_WITH_MFC)
|
||||||
std::wstring ToWString(const CString & x) { return mpt::ToWide(x); }
|
std::wstring ToWString(const CString & x) { return mpt::ToWide(x); }
|
||||||
#endif
|
#endif // MPT_WITH_MFC
|
||||||
std::wstring ToWString(const bool & x) { return ToWStringHelperInt(static_cast<int>(x)); }
|
std::wstring ToWString(const bool & x) { return ToWStringHelperInt(static_cast<int>(x)); }
|
||||||
std::wstring ToWString(const signed char & x) { return ToWStringHelperInt(x); }
|
std::wstring ToWString(const signed char & x) { return ToWStringHelperInt(x); }
|
||||||
std::wstring ToWString(const unsigned char & x) { return ToWStringHelperInt(x); }
|
std::wstring ToWString(const unsigned char & x) { return ToWStringHelperInt(x); }
|
||||||
|
@ -468,10 +450,6 @@ static inline std::wstring FormatValWHelperFloat(const T & x, const FormatSpec &
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
std::string FormatVal(const char & x, const FormatSpec & f) { return FormatValHelperInt(x, f); }
|
|
||||||
#if !defined(MPT_COMPILER_QUIRK_NO_WCHAR)
|
|
||||||
std::string FormatVal(const wchar_t & x, const FormatSpec & f) { return FormatValHelperInt(x, f); }
|
|
||||||
#endif // !MPT_COMPILER_QUIRK_NO_WCHAR
|
|
||||||
std::string FormatVal(const bool & x, const FormatSpec & f) { return FormatValHelperInt(static_cast<int>(x), f); }
|
std::string FormatVal(const bool & x, const FormatSpec & f) { return FormatValHelperInt(static_cast<int>(x), f); }
|
||||||
std::string FormatVal(const signed char & x, const FormatSpec & f) { return FormatValHelperInt(x, f); }
|
std::string FormatVal(const signed char & x, const FormatSpec & f) { return FormatValHelperInt(x, f); }
|
||||||
std::string FormatVal(const unsigned char & x, const FormatSpec & f) { return FormatValHelperInt(x, f); }
|
std::string FormatVal(const unsigned char & x, const FormatSpec & f) { return FormatValHelperInt(x, f); }
|
||||||
|
@ -488,8 +466,6 @@ std::string FormatVal(const double & x, const FormatSpec & f) { return FormatVal
|
||||||
std::string FormatVal(const long double & x, const FormatSpec & f) { return FormatValHelperFloat(x, f); }
|
std::string FormatVal(const long double & x, const FormatSpec & f) { return FormatValHelperFloat(x, f); }
|
||||||
|
|
||||||
#if MPT_USTRING_MODE_WIDE
|
#if MPT_USTRING_MODE_WIDE
|
||||||
mpt::ustring FormatValU(const char & x, const FormatSpec & f) { return FormatValWHelperInt(x, f); }
|
|
||||||
mpt::ustring FormatValU(const wchar_t & x, const FormatSpec & f) { return FormatValWHelperInt(x, f); }
|
|
||||||
mpt::ustring FormatValU(const bool & x, const FormatSpec & f) { return FormatValWHelperInt(static_cast<int>(x), f); }
|
mpt::ustring FormatValU(const bool & x, const FormatSpec & f) { return FormatValWHelperInt(static_cast<int>(x), f); }
|
||||||
mpt::ustring FormatValU(const signed char & x, const FormatSpec & f) { return FormatValWHelperInt(x, f); }
|
mpt::ustring FormatValU(const signed char & x, const FormatSpec & f) { return FormatValWHelperInt(x, f); }
|
||||||
mpt::ustring FormatValU(const unsigned char & x, const FormatSpec & f) { return FormatValWHelperInt(x, f); }
|
mpt::ustring FormatValU(const unsigned char & x, const FormatSpec & f) { return FormatValWHelperInt(x, f); }
|
||||||
|
@ -506,31 +482,23 @@ mpt::ustring FormatValU(const double & x, const FormatSpec & f) { return FormatV
|
||||||
mpt::ustring FormatValU(const long double & x, const FormatSpec & f) { return FormatValWHelperFloat(x, f); }
|
mpt::ustring FormatValU(const long double & x, const FormatSpec & f) { return FormatValWHelperFloat(x, f); }
|
||||||
#endif
|
#endif
|
||||||
#if MPT_USTRING_MODE_UTF8
|
#if MPT_USTRING_MODE_UTF8
|
||||||
mpt::ustring FormatValU(const char & x, const FormatSpec & f) { return mpt::ToUnicode(mpt::CharsetUTF8, FormatValHelperInt(x, f)); }
|
mpt::ustring FormatValU(const bool & x, const FormatSpec & f) { return mpt::ToUnicode(mpt::Charset::UTF8, FormatValHelperInt(static_cast<int>(x), f)); }
|
||||||
#if !defined(MPT_COMPILER_QUIRK_NO_WCHAR)
|
mpt::ustring FormatValU(const signed char & x, const FormatSpec & f) { return mpt::ToUnicode(mpt::Charset::UTF8, FormatValHelperInt(x, f)); }
|
||||||
mpt::ustring FormatValU(const wchar_t & x, const FormatSpec & f) { return mpt::ToUnicode(mpt::CharsetUTF8, FormatValHelperInt(x, f)); }
|
mpt::ustring FormatValU(const unsigned char & x, const FormatSpec & f) { return mpt::ToUnicode(mpt::Charset::UTF8, FormatValHelperInt(x, f)); }
|
||||||
#endif // !MPT_COMPILER_QUIRK_NO_WCHAR
|
mpt::ustring FormatValU(const signed short & x, const FormatSpec & f) { return mpt::ToUnicode(mpt::Charset::UTF8, FormatValHelperInt(x, f)); }
|
||||||
mpt::ustring FormatValU(const bool & x, const FormatSpec & f) { return mpt::ToUnicode(mpt::CharsetUTF8, FormatValHelperInt(static_cast<int>(x), f)); }
|
mpt::ustring FormatValU(const unsigned short & x, const FormatSpec & f) { return mpt::ToUnicode(mpt::Charset::UTF8, FormatValHelperInt(x, f)); }
|
||||||
mpt::ustring FormatValU(const signed char & x, const FormatSpec & f) { return mpt::ToUnicode(mpt::CharsetUTF8, FormatValHelperInt(x, f)); }
|
mpt::ustring FormatValU(const signed int & x, const FormatSpec & f) { return mpt::ToUnicode(mpt::Charset::UTF8, FormatValHelperInt(x, f)); }
|
||||||
mpt::ustring FormatValU(const unsigned char & x, const FormatSpec & f) { return mpt::ToUnicode(mpt::CharsetUTF8, FormatValHelperInt(x, f)); }
|
mpt::ustring FormatValU(const unsigned int & x, const FormatSpec & f) { return mpt::ToUnicode(mpt::Charset::UTF8, FormatValHelperInt(x, f)); }
|
||||||
mpt::ustring FormatValU(const signed short & x, const FormatSpec & f) { return mpt::ToUnicode(mpt::CharsetUTF8, FormatValHelperInt(x, f)); }
|
mpt::ustring FormatValU(const signed long & x, const FormatSpec & f) { return mpt::ToUnicode(mpt::Charset::UTF8, FormatValHelperInt(x, f)); }
|
||||||
mpt::ustring FormatValU(const unsigned short & x, const FormatSpec & f) { return mpt::ToUnicode(mpt::CharsetUTF8, FormatValHelperInt(x, f)); }
|
mpt::ustring FormatValU(const unsigned long & x, const FormatSpec & f) { return mpt::ToUnicode(mpt::Charset::UTF8, FormatValHelperInt(x, f)); }
|
||||||
mpt::ustring FormatValU(const signed int & x, const FormatSpec & f) { return mpt::ToUnicode(mpt::CharsetUTF8, FormatValHelperInt(x, f)); }
|
mpt::ustring FormatValU(const signed long long & x, const FormatSpec & f) { return mpt::ToUnicode(mpt::Charset::UTF8, FormatValHelperInt(x, f)); }
|
||||||
mpt::ustring FormatValU(const unsigned int & x, const FormatSpec & f) { return mpt::ToUnicode(mpt::CharsetUTF8, FormatValHelperInt(x, f)); }
|
mpt::ustring FormatValU(const unsigned long long & x, const FormatSpec & f) { return mpt::ToUnicode(mpt::Charset::UTF8, FormatValHelperInt(x, f)); }
|
||||||
mpt::ustring FormatValU(const signed long & x, const FormatSpec & f) { return mpt::ToUnicode(mpt::CharsetUTF8, FormatValHelperInt(x, f)); }
|
mpt::ustring FormatValU(const float & x, const FormatSpec & f) { return mpt::ToUnicode(mpt::Charset::UTF8, FormatValHelperFloat(x, f)); }
|
||||||
mpt::ustring FormatValU(const unsigned long & x, const FormatSpec & f) { return mpt::ToUnicode(mpt::CharsetUTF8, FormatValHelperInt(x, f)); }
|
mpt::ustring FormatValU(const double & x, const FormatSpec & f) { return mpt::ToUnicode(mpt::Charset::UTF8, FormatValHelperFloat(x, f)); }
|
||||||
mpt::ustring FormatValU(const signed long long & x, const FormatSpec & f) { return mpt::ToUnicode(mpt::CharsetUTF8, FormatValHelperInt(x, f)); }
|
mpt::ustring FormatValU(const long double & x, const FormatSpec & f) { return mpt::ToUnicode(mpt::Charset::UTF8, FormatValHelperFloat(x, f)); }
|
||||||
mpt::ustring FormatValU(const unsigned long long & x, const FormatSpec & f) { return mpt::ToUnicode(mpt::CharsetUTF8, FormatValHelperInt(x, f)); }
|
|
||||||
mpt::ustring FormatValU(const float & x, const FormatSpec & f) { return mpt::ToUnicode(mpt::CharsetUTF8, FormatValHelperFloat(x, f)); }
|
|
||||||
mpt::ustring FormatValU(const double & x, const FormatSpec & f) { return mpt::ToUnicode(mpt::CharsetUTF8, FormatValHelperFloat(x, f)); }
|
|
||||||
mpt::ustring FormatValU(const long double & x, const FormatSpec & f) { return mpt::ToUnicode(mpt::CharsetUTF8, FormatValHelperFloat(x, f)); }
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MPT_WSTRING_FORMAT
|
#if MPT_WSTRING_FORMAT
|
||||||
std::wstring FormatValW(const char & x, const FormatSpec & f) { return FormatValWHelperInt(x, f); }
|
|
||||||
#if !defined(MPT_COMPILER_QUIRK_NO_WCHAR)
|
|
||||||
std::wstring FormatValW(const wchar_t & x, const FormatSpec & f) { return FormatValWHelperInt(x, f); }
|
|
||||||
#endif // !MPT_COMPILER_QUIRK_NO_WCHAR
|
|
||||||
std::wstring FormatValW(const bool & x, const FormatSpec & f) { return FormatValWHelperInt(static_cast<int>(x), f); }
|
std::wstring FormatValW(const bool & x, const FormatSpec & f) { return FormatValWHelperInt(static_cast<int>(x), f); }
|
||||||
std::wstring FormatValW(const signed char & x, const FormatSpec & f) { return FormatValWHelperInt(x, f); }
|
std::wstring FormatValW(const signed char & x, const FormatSpec & f) { return FormatValWHelperInt(x, f); }
|
||||||
std::wstring FormatValW(const unsigned char & x, const FormatSpec & f) { return FormatValWHelperInt(x, f); }
|
std::wstring FormatValW(const unsigned char & x, const FormatSpec & f) { return FormatValWHelperInt(x, f); }
|
||||||
|
@ -548,145 +516,6 @@ std::wstring FormatValW(const long double & x, const FormatSpec & f) { return Fo
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
namespace String
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
|
|
||||||
template<typename Tstring>
|
|
||||||
Tstring PrintImplTemplate(const Tstring & format
|
|
||||||
, const Tstring & x1
|
|
||||||
, const Tstring & x2
|
|
||||||
, const Tstring & x3
|
|
||||||
, const Tstring & x4
|
|
||||||
, const Tstring & x5
|
|
||||||
, const Tstring & x6
|
|
||||||
, const Tstring & x7
|
|
||||||
, const Tstring & x8
|
|
||||||
)
|
|
||||||
{
|
|
||||||
typedef typename mpt::string_traits<Tstring> traits;
|
|
||||||
Tstring result;
|
|
||||||
const typename traits::size_type len = traits::length(format);
|
|
||||||
traits::reserve(result, len);
|
|
||||||
for(typename traits::size_type pos = 0; pos != len; ++pos)
|
|
||||||
{
|
|
||||||
typename traits::char_type c = format[pos];
|
|
||||||
if(pos + 1 != len && c == typename traits::char_type('%'))
|
|
||||||
{
|
|
||||||
pos++;
|
|
||||||
c = format[pos];
|
|
||||||
if(typename traits::char_type('1') <= c && c <= typename traits::char_type('9'))
|
|
||||||
{
|
|
||||||
const std::size_t n = c - typename traits::char_type('0');
|
|
||||||
switch(n)
|
|
||||||
{
|
|
||||||
case 1: traits::append(result, x1); break;
|
|
||||||
case 2: traits::append(result, x2); break;
|
|
||||||
case 3: traits::append(result, x3); break;
|
|
||||||
case 4: traits::append(result, x4); break;
|
|
||||||
case 5: traits::append(result, x5); break;
|
|
||||||
case 6: traits::append(result, x6); break;
|
|
||||||
case 7: traits::append(result, x7); break;
|
|
||||||
case 8: traits::append(result, x8); break;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
} else if(c != typename traits::char_type('%'))
|
|
||||||
{
|
|
||||||
traits::append(result, 1, typename traits::char_type('%'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
traits::append(result, 1, c);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string PrintImpl(const std::string & format
|
|
||||||
, const std::string & x1
|
|
||||||
, const std::string & x2
|
|
||||||
, const std::string & x3
|
|
||||||
, const std::string & x4
|
|
||||||
, const std::string & x5
|
|
||||||
, const std::string & x6
|
|
||||||
, const std::string & x7
|
|
||||||
, const std::string & x8
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return PrintImplTemplate<std::string>(format, x1,x2,x3,x4,x5,x6,x7,x8);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if MPT_WSTRING_FORMAT
|
|
||||||
std::wstring PrintImpl(const std::wstring & format
|
|
||||||
, const std::wstring & x1
|
|
||||||
, const std::wstring & x2
|
|
||||||
, const std::wstring & x3
|
|
||||||
, const std::wstring & x4
|
|
||||||
, const std::wstring & x5
|
|
||||||
, const std::wstring & x6
|
|
||||||
, const std::wstring & x7
|
|
||||||
, const std::wstring & x8
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return PrintImplTemplate<std::wstring>(format, x1,x2,x3,x4,x5,x6,x7,x8);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if MPT_USTRING_MODE_UTF8
|
|
||||||
mpt::ustring PrintImpl(const mpt::ustring & format
|
|
||||||
, const mpt::ustring & x1
|
|
||||||
, const mpt::ustring & x2
|
|
||||||
, const mpt::ustring & x3
|
|
||||||
, const mpt::ustring & x4
|
|
||||||
, const mpt::ustring & x5
|
|
||||||
, const mpt::ustring & x6
|
|
||||||
, const mpt::ustring & x7
|
|
||||||
, const mpt::ustring & x8
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return PrintImplTemplate<mpt::ustring>(format, x1,x2,x3,x4,x5,x6,x7,x8);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
|
||||||
mpt::lstring PrintImpl(const mpt::lstring & format
|
|
||||||
, const mpt::lstring & x1
|
|
||||||
, const mpt::lstring & x2
|
|
||||||
, const mpt::lstring & x3
|
|
||||||
, const mpt::lstring & x4
|
|
||||||
, const mpt::lstring & x5
|
|
||||||
, const mpt::lstring & x6
|
|
||||||
, const mpt::lstring & x7
|
|
||||||
, const mpt::lstring & x8
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return PrintImplTemplate<mpt::lstring>(format, x1,x2,x3,x4,x5,x6,x7,x8);
|
|
||||||
}
|
|
||||||
#endif // MPT_ENABLE_CHARSET_LOCALE
|
|
||||||
|
|
||||||
#if defined(_MFC_VER)
|
|
||||||
CString PrintImpl(const CString & format
|
|
||||||
, const CString & x1
|
|
||||||
, const CString & x2
|
|
||||||
, const CString & x3
|
|
||||||
, const CString & x4
|
|
||||||
, const CString & x5
|
|
||||||
, const CString & x6
|
|
||||||
, const CString & x7
|
|
||||||
, const CString & x8
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return PrintImplTemplate<CString>(format, x1,x2,x3,x4,x5,x6,x7,x8);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace String
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace mpt
|
} // namespace mpt
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -71,25 +71,25 @@ namespace mpt
|
||||||
|
|
||||||
// fallback to member function ToUString()
|
// fallback to member function ToUString()
|
||||||
#if MPT_USTRING_MODE_UTF8
|
#if MPT_USTRING_MODE_UTF8
|
||||||
template <typename T> auto ToString(const T & x) -> decltype(mpt::ToCharset(mpt::CharsetUTF8, x.ToUString())) { return mpt::ToCharset(mpt::CharsetUTF8, x.ToUString()); }
|
template <typename T> auto ToString(const T & x) -> decltype(mpt::ToCharset(mpt::Charset::UTF8, x.ToUString())) { return mpt::ToCharset(mpt::Charset::UTF8, x.ToUString()); }
|
||||||
#else
|
#else
|
||||||
template <typename T> auto ToString(const T & x) -> decltype(mpt::ToCharset(mpt::CharsetLocaleOrUTF8, x.ToUString())) { return mpt::ToCharset(mpt::CharsetLocaleOrUTF8, x.ToUString()); }
|
template <typename T> auto ToString(const T & x) -> decltype(mpt::ToCharset(mpt::CharsetLocaleOrUTF8, x.ToUString())) { return mpt::ToCharset(mpt::CharsetLocaleOrUTF8, x.ToUString()); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static inline std::string ToString(const std::string & x) { return x; }
|
static inline std::string ToString(const std::string & x) { return x; }
|
||||||
static inline std::string ToString(const char * const & x) { return x; }
|
static inline std::string ToString(const char * const & x) { return x; }
|
||||||
MPT_DEPRECATED static inline std::string ToString(const char & x) { return std::string(1, x); } // deprecated to catch potential API mis-use, use std::string(1, x) instead
|
std::string ToString(const char &x) = delete; // deprecated to catch potential API mis-use, use std::string(1, x) instead
|
||||||
#if MPT_WSTRING_FORMAT
|
#if MPT_WSTRING_FORMAT
|
||||||
MPT_DEPRECATED std::string ToString(const std::wstring & x); // Unknown encoding.
|
std::string ToString(const std::wstring & x) = delete; // Unknown encoding.
|
||||||
MPT_DEPRECATED std::string ToString(const wchar_t * const & x); // Unknown encoding.
|
std::string ToString(const wchar_t * const & x) = delete; // Unknown encoding.
|
||||||
MPT_DEPRECATED std::string ToString(const wchar_t & x); // deprecated to catch potential API mis-use, use std::wstring(1, x) instead
|
std::string ToString(const wchar_t &x ) = delete; // deprecated to catch potential API mis-use, use std::wstring(1, x) instead
|
||||||
#endif
|
#endif
|
||||||
#if MPT_USTRING_MODE_UTF8
|
#if MPT_USTRING_MODE_UTF8
|
||||||
MPT_DEPRECATED std::string ToString(const mpt::ustring & x); // Unknown encoding.
|
std::string ToString(const mpt::ustring & x) = delete; // Unknown encoding.
|
||||||
#endif
|
|
||||||
#if defined(_MFC_VER)
|
|
||||||
MPT_DEPRECATED std::string ToString(const CString & x);
|
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(MPT_WITH_MFC)
|
||||||
|
std::string ToString(const CString & x) = delete; // unknown encoding
|
||||||
|
#endif // MPT_WITH_MFC
|
||||||
std::string ToString(const bool & x);
|
std::string ToString(const bool & x);
|
||||||
std::string ToString(const signed char & x);
|
std::string ToString(const signed char & x);
|
||||||
std::string ToString(const unsigned char & x);
|
std::string ToString(const unsigned char & x);
|
||||||
|
@ -109,19 +109,19 @@ std::string ToString(const long double & x);
|
||||||
template <typename T> auto ToUString(const T & x) -> decltype(x.ToUString()) { return x.ToUString(); }
|
template <typename T> auto ToUString(const T & x) -> decltype(x.ToUString()) { return x.ToUString(); }
|
||||||
|
|
||||||
static inline mpt::ustring ToUString(const mpt::ustring & x) { return x; }
|
static inline mpt::ustring ToUString(const mpt::ustring & x) { return x; }
|
||||||
MPT_DEPRECATED mpt::ustring ToUString(const std::string & x); // Unknown encoding.
|
mpt::ustring ToUString(const std::string & x) = delete; // Unknown encoding.
|
||||||
MPT_DEPRECATED mpt::ustring ToUString(const char * const & x); // Unknown encoding. Note that this also applies to TCHAR in !UNICODE builds as the type is indistinguishable from char. Wrap with CString or FromTcharStr in this case.
|
mpt::ustring ToUString(const char * const & x) = delete; // Unknown encoding. Note that this also applies to TCHAR in !UNICODE builds as the type is indistinguishable from char. Wrap with CString or FromTcharStr in this case.
|
||||||
MPT_DEPRECATED mpt::ustring ToUString(const char & x); // deprecated to catch potential API mis-use, use std::string(1, x) instead
|
mpt::ustring ToUString(const char & x) = delete; // deprecated to catch potential API mis-use, use std::string(1, x) instead
|
||||||
#if MPT_WSTRING_FORMAT
|
#if MPT_WSTRING_FORMAT
|
||||||
#if MPT_USTRING_MODE_UTF8
|
#if MPT_USTRING_MODE_UTF8
|
||||||
mpt::ustring ToUString(const std::wstring & x);
|
mpt::ustring ToUString(const std::wstring & x);
|
||||||
#endif
|
#endif
|
||||||
mpt::ustring ToUString(const wchar_t * const & x);
|
mpt::ustring ToUString(const wchar_t * const & x);
|
||||||
MPT_DEPRECATED mpt::ustring ToUString(const wchar_t & x); // deprecated to catch potential API mis-use, use std::wstring(1, x) instead
|
mpt::ustring ToUString(const wchar_t & x) = delete; // deprecated to catch potential API mis-use, use std::wstring(1, x) instead
|
||||||
#endif
|
#endif
|
||||||
#if defined(_MFC_VER)
|
#if defined(MPT_WITH_MFC)
|
||||||
mpt::ustring ToUString(const CString & x);
|
mpt::ustring ToUString(const CString & x);
|
||||||
#endif
|
#endif // MPT_WITH_MFC
|
||||||
mpt::ustring ToUString(const bool & x);
|
mpt::ustring ToUString(const bool & x);
|
||||||
mpt::ustring ToUString(const signed char & x);
|
mpt::ustring ToUString(const signed char & x);
|
||||||
mpt::ustring ToUString(const unsigned char & x);
|
mpt::ustring ToUString(const unsigned char & x);
|
||||||
|
@ -138,18 +138,18 @@ mpt::ustring ToUString(const double & x);
|
||||||
mpt::ustring ToUString(const long double & x);
|
mpt::ustring ToUString(const long double & x);
|
||||||
|
|
||||||
#if MPT_WSTRING_FORMAT
|
#if MPT_WSTRING_FORMAT
|
||||||
MPT_DEPRECATED std::wstring ToWString(const std::string & x); // Unknown encoding.
|
std::wstring ToWString(const std::string & x) = delete; // Unknown encoding.
|
||||||
MPT_DEPRECATED std::wstring ToWString(const char * const & x); // Unknown encoding. Note that this also applies to TCHAR in !UNICODE builds as the type is indistinguishable from char. Wrap with CString or FromTcharStr in this case.
|
std::wstring ToWString(const char * const & x) = delete; // Unknown encoding. Note that this also applies to TCHAR in !UNICODE builds as the type is indistinguishable from char. Wrap with CString or FromTcharStr in this case.
|
||||||
MPT_DEPRECATED std::wstring ToWString(const char & x); // deprecated to catch potential API mis-use, use std::string(1, x) instead
|
std::wstring ToWString(const char & x) = delete; // deprecated to catch potential API mis-use, use std::string(1, x) instead
|
||||||
static inline std::wstring ToWString(const std::wstring & x) { return x; }
|
static inline std::wstring ToWString(const std::wstring & x) { return x; }
|
||||||
static inline std::wstring ToWString(const wchar_t * const & x) { return x; }
|
static inline std::wstring ToWString(const wchar_t * const & x) { return x; }
|
||||||
MPT_DEPRECATED static inline std::wstring ToWString(const wchar_t & x) { return std::wstring(1, x); } // deprecated to catch potential API mis-use, use std::wstring(1, x) instead
|
std::wstring ToWString(const wchar_t & x) = delete; // deprecated to catch potential API mis-use, use std::wstring(1, x) instead
|
||||||
#if MPT_USTRING_MODE_UTF8
|
#if MPT_USTRING_MODE_UTF8
|
||||||
std::wstring ToWString(const mpt::ustring & x);
|
std::wstring ToWString(const mpt::ustring & x);
|
||||||
#endif
|
#endif
|
||||||
#if defined(_MFC_VER)
|
#if defined(MPT_WITH_MFC)
|
||||||
std::wstring ToWString(const CString & x);
|
std::wstring ToWString(const CString & x);
|
||||||
#endif
|
#endif // MPT_WITH_MFC
|
||||||
std::wstring ToWString(const bool & x);
|
std::wstring ToWString(const bool & x);
|
||||||
std::wstring ToWString(const signed char & x);
|
std::wstring ToWString(const signed char & x);
|
||||||
std::wstring ToWString(const unsigned char & x);
|
std::wstring ToWString(const unsigned char & x);
|
||||||
|
@ -173,10 +173,10 @@ template <typename T> struct ToLocaleHelper { mpt::lstring operator () (const T
|
||||||
template <> struct ToLocaleHelper<mpt::lstring> { mpt::lstring operator () (const mpt::lstring & v) { return v; } };
|
template <> struct ToLocaleHelper<mpt::lstring> { mpt::lstring operator () (const mpt::lstring & v) { return v; } };
|
||||||
#endif // MPT_ENABLE_CHARSET_LOCALE
|
#endif // MPT_ENABLE_CHARSET_LOCALE
|
||||||
|
|
||||||
#if defined(_MFC_VER)
|
#if defined(MPT_WITH_MFC)
|
||||||
template <typename T> struct ToCStringHelper { CString operator () (const T & v) { return mpt::ToCString(ToUString(v)); } };
|
template <typename T> struct ToCStringHelper { CString operator () (const T & v) { return mpt::ToCString(ToUString(v)); } };
|
||||||
template <> struct ToCStringHelper<CString> { CString operator () (const CString & v) { return v; } };
|
template <> struct ToCStringHelper<CString> { CString operator () (const CString & v) { return v; } };
|
||||||
#endif
|
#endif // MPT_WITH_MFC
|
||||||
|
|
||||||
template <typename Tstring> struct ToStringTFunctor {};
|
template <typename Tstring> struct ToStringTFunctor {};
|
||||||
template <> struct ToStringTFunctor<std::string> { template <typename T> inline std::string operator() (const T & x) { return ToString(x); } };
|
template <> struct ToStringTFunctor<std::string> { template <typename T> inline std::string operator() (const T & x) { return ToString(x); } };
|
||||||
|
@ -187,9 +187,9 @@ template <> struct ToStringTFunctor<std::wstring> { template <typename T> inline
|
||||||
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
||||||
template <> struct ToStringTFunctor<mpt::lstring> { template <typename T> inline mpt::lstring operator() (const T & x) { return mpt::ToLocaleHelper<T>()(x); } };
|
template <> struct ToStringTFunctor<mpt::lstring> { template <typename T> inline mpt::lstring operator() (const T & x) { return mpt::ToLocaleHelper<T>()(x); } };
|
||||||
#endif // MPT_ENABLE_CHARSET_LOCALE
|
#endif // MPT_ENABLE_CHARSET_LOCALE
|
||||||
#if defined(_MFC_VER)
|
#if defined(MPT_WITH_MFC)
|
||||||
template <> struct ToStringTFunctor<CString> { template <typename T> inline CString operator() (const T & x) { return mpt::ToCStringHelper<T>()(x); } };
|
template <> struct ToStringTFunctor<CString> { template <typename T> inline CString operator() (const T & x) { return mpt::ToCStringHelper<T>()(x); } };
|
||||||
#endif
|
#endif // MPT_WITH_MFC
|
||||||
|
|
||||||
template<typename Tstring, typename T> inline Tstring ToStringT(const T & x) { return ToStringTFunctor<Tstring>()(x); }
|
template<typename Tstring, typename T> inline Tstring ToStringT(const T & x) { return ToStringTFunctor<Tstring>()(x); }
|
||||||
|
|
||||||
|
@ -215,13 +215,13 @@ enum FormatFlagsEnum
|
||||||
|
|
||||||
typedef unsigned int FormatFlags;
|
typedef unsigned int FormatFlags;
|
||||||
|
|
||||||
STATIC_ASSERT(sizeof(FormatFlags) >= sizeof(fmt_base::FormatFlagsEnum));
|
static_assert(sizeof(FormatFlags) >= sizeof(fmt_base::FormatFlagsEnum));
|
||||||
|
|
||||||
class FormatSpec;
|
class FormatSpec;
|
||||||
|
|
||||||
MPT_DEPRECATED std::string FormatVal(const char & x, const FormatSpec & f); // deprecated to catch potential API mis-use, use std::string(1, x) instead
|
std::string FormatVal(const char & x, const FormatSpec & f) = delete; // deprecated to catch potential API mis-use, use std::string(1, x) instead
|
||||||
#if !defined(MPT_COMPILER_QUIRK_NO_WCHAR)
|
#if !defined(MPT_COMPILER_QUIRK_NO_WCHAR)
|
||||||
MPT_DEPRECATED std::string FormatVal(const wchar_t & x, const FormatSpec & f); // deprecated to catch potential API mis-use, use std::wstring(1, x) instead
|
std::string FormatVal(const wchar_t & x, const FormatSpec & f) = delete; // deprecated to catch potential API mis-use, use std::wstring(1, x) instead
|
||||||
#endif // !MPT_COMPILER_QUIRK_NO_WCHAR
|
#endif // !MPT_COMPILER_QUIRK_NO_WCHAR
|
||||||
std::string FormatVal(const bool & x, const FormatSpec & f);
|
std::string FormatVal(const bool & x, const FormatSpec & f);
|
||||||
std::string FormatVal(const signed char & x, const FormatSpec & f);
|
std::string FormatVal(const signed char & x, const FormatSpec & f);
|
||||||
|
@ -238,9 +238,9 @@ std::string FormatVal(const float & x, const FormatSpec & f);
|
||||||
std::string FormatVal(const double & x, const FormatSpec & f);
|
std::string FormatVal(const double & x, const FormatSpec & f);
|
||||||
std::string FormatVal(const long double & x, const FormatSpec & f);
|
std::string FormatVal(const long double & x, const FormatSpec & f);
|
||||||
|
|
||||||
MPT_DEPRECATED mpt::ustring FormatValU(const char & x, const FormatSpec & f); // deprecated to catch potential API mis-use, use std::string(1, x) instead
|
mpt::ustring FormatValU(const char & x, const FormatSpec & f) = delete; // deprecated to catch potential API mis-use, use std::string(1, x) instead
|
||||||
#if !defined(MPT_COMPILER_QUIRK_NO_WCHAR)
|
#if !defined(MPT_COMPILER_QUIRK_NO_WCHAR)
|
||||||
MPT_DEPRECATED mpt::ustring FormatValU(const wchar_t & x, const FormatSpec & f); // deprecated to catch potential API mis-use, use std::wstring(1, x) instead
|
mpt::ustring FormatValU(const wchar_t & x, const FormatSpec & f) = delete; // deprecated to catch potential API mis-use, use std::wstring(1, x) instead
|
||||||
#endif // !MPT_COMPILER_QUIRK_NO_WCHAR
|
#endif // !MPT_COMPILER_QUIRK_NO_WCHAR
|
||||||
mpt::ustring FormatValU(const bool & x, const FormatSpec & f);
|
mpt::ustring FormatValU(const bool & x, const FormatSpec & f);
|
||||||
mpt::ustring FormatValU(const signed char & x, const FormatSpec & f);
|
mpt::ustring FormatValU(const signed char & x, const FormatSpec & f);
|
||||||
|
@ -258,9 +258,9 @@ mpt::ustring FormatValU(const double & x, const FormatSpec & f);
|
||||||
mpt::ustring FormatValU(const long double & x, const FormatSpec & f);
|
mpt::ustring FormatValU(const long double & x, const FormatSpec & f);
|
||||||
|
|
||||||
#if MPT_WSTRING_FORMAT
|
#if MPT_WSTRING_FORMAT
|
||||||
MPT_DEPRECATED std::wstring FormatValW(const char & x, const FormatSpec & f); // deprecated to catch potential API mis-use, use std::string(1, x) instead
|
std::wstring FormatValW(const char & x, const FormatSpec & f) = delete; // deprecated to catch potential API mis-use, use std::string(1, x) instead
|
||||||
#if !defined(MPT_COMPILER_QUIRK_NO_WCHAR)
|
#if !defined(MPT_COMPILER_QUIRK_NO_WCHAR)
|
||||||
MPT_DEPRECATED std::wstring FormatValW(const wchar_t & x, const FormatSpec & f); // deprecated to catch potential API mis-use, use std::wstring(1, x) instead
|
std::wstring FormatValW(const wchar_t & x, const FormatSpec & f) = delete; // deprecated to catch potential API mis-use, use std::wstring(1, x) instead
|
||||||
#endif // !MPT_COMPILER_QUIRK_NO_WCHAR
|
#endif // !MPT_COMPILER_QUIRK_NO_WCHAR
|
||||||
std::wstring FormatValW(const bool & x, const FormatSpec & f);
|
std::wstring FormatValW(const bool & x, const FormatSpec & f);
|
||||||
std::wstring FormatValW(const signed char & x, const FormatSpec & f);
|
std::wstring FormatValW(const signed char & x, const FormatSpec & f);
|
||||||
|
@ -285,15 +285,15 @@ template <> struct FormatValTFunctor<mpt::ustring> { template <typename T> inlin
|
||||||
template <> struct FormatValTFunctor<std::wstring> { template <typename T> inline std::wstring operator() (const T & x, const FormatSpec & f) { return FormatValW(x, f); } };
|
template <> struct FormatValTFunctor<std::wstring> { template <typename T> inline std::wstring operator() (const T & x, const FormatSpec & f) { return FormatValW(x, f); } };
|
||||||
#endif
|
#endif
|
||||||
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
||||||
template <> struct FormatValTFunctor<mpt::lstring> { template <typename T> inline mpt::lstring operator() (const T & x, const FormatSpec & f) { return mpt::ToLocale(mpt::CharsetLocale, FormatVal(x, f)); } };
|
template <> struct FormatValTFunctor<mpt::lstring> { template <typename T> inline mpt::lstring operator() (const T & x, const FormatSpec & f) { return mpt::ToLocale(mpt::Charset::Locale, FormatVal(x, f)); } };
|
||||||
#endif // MPT_ENABLE_CHARSET_LOCALE
|
#endif // MPT_ENABLE_CHARSET_LOCALE
|
||||||
#if defined(_MFC_VER)
|
#if defined(MPT_WITH_MFC )
|
||||||
#ifdef UNICODE
|
#ifdef UNICODE
|
||||||
template <> struct FormatValTFunctor<CString> { template <typename T> inline CString operator() (const T & x, const FormatSpec & f) { return mpt::ToCString(FormatValW(x, f)); } };
|
template <> struct FormatValTFunctor<CString> { template <typename T> inline CString operator() (const T & x, const FormatSpec & f) { return mpt::ToCString(FormatValW(x, f)); } };
|
||||||
#else
|
#else // !UNICODE
|
||||||
template <> struct FormatValTFunctor<CString> { template <typename T> inline CString operator() (const T & x, const FormatSpec & f) { return mpt::ToCString(mpt::CharsetLocale, FormatVal(x, f)); } };
|
template <> struct FormatValTFunctor<CString> { template <typename T> inline CString operator() (const T & x, const FormatSpec & f) { return mpt::ToCString(mpt::Charset::Locale, FormatVal(x, f)); } };
|
||||||
#endif
|
#endif // UNICODE
|
||||||
#endif
|
#endif // MPT_WITH_MFC
|
||||||
|
|
||||||
|
|
||||||
class FormatSpec
|
class FormatSpec
|
||||||
|
@ -353,6 +353,28 @@ public:
|
||||||
MPT_CONSTEXPR14_FUN FormatSpec & Precision(int p) noexcept { return Prec(p); }
|
MPT_CONSTEXPR14_FUN FormatSpec & Precision(int p) noexcept { return Prec(p); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename Tdst, typename Tsrc>
|
||||||
|
struct pointer_cast_helper
|
||||||
|
{
|
||||||
|
Tdst operator()(const Tsrc & src) const { return src; }
|
||||||
|
};
|
||||||
|
template <typename Tdst, typename Tptr>
|
||||||
|
struct pointer_cast_helper<Tdst, const Tptr*>
|
||||||
|
{
|
||||||
|
Tdst operator()(const Tptr * const & src) const { return reinterpret_cast<const Tdst>(src); }
|
||||||
|
};
|
||||||
|
template <typename Tdst, typename Tptr>
|
||||||
|
struct pointer_cast_helper<Tdst, Tptr*>
|
||||||
|
{
|
||||||
|
Tdst operator()(const Tptr * const & src) const { return reinterpret_cast<const Tdst>(src); }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename Tdst, typename Tsrc>
|
||||||
|
Tdst pointer_cast(const Tsrc & src)
|
||||||
|
{
|
||||||
|
return pointer_cast_helper<Tdst, Tsrc>()(src);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Tstring>
|
template <typename Tstring>
|
||||||
struct fmtT : fmt_base
|
struct fmtT : fmt_base
|
||||||
|
@ -373,98 +395,111 @@ static inline Tstring fmt(const T& x, const FormatSpec& f)
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static inline Tstring dec(const T& x)
|
static inline Tstring dec(const T& x)
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(std::numeric_limits<T>::is_integer);
|
static_assert(std::numeric_limits<T>::is_integer);
|
||||||
return FormatValTFunctor<Tstring>()(x, FormatSpec().BaseDec().FillOff());
|
return FormatValTFunctor<Tstring>()(x, FormatSpec().BaseDec().FillOff());
|
||||||
}
|
}
|
||||||
template<int width, typename T>
|
template<int width, typename T>
|
||||||
static inline Tstring dec0(const T& x)
|
static inline Tstring dec0(const T& x)
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(std::numeric_limits<T>::is_integer);
|
static_assert(std::numeric_limits<T>::is_integer);
|
||||||
return FormatValTFunctor<Tstring>()(x, FormatSpec().BaseDec().FillNul().Width(width));
|
return FormatValTFunctor<Tstring>()(x, FormatSpec().BaseDec().FillNul().Width(width));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static inline Tstring dec(unsigned int g, char s, const T& x)
|
static inline Tstring dec(unsigned int g, char s, const T& x)
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(std::numeric_limits<T>::is_integer);
|
static_assert(std::numeric_limits<T>::is_integer);
|
||||||
return FormatValTFunctor<Tstring>()(x, FormatSpec().BaseDec().FillOff().Group(g).GroupSep(s));
|
return FormatValTFunctor<Tstring>()(x, FormatSpec().BaseDec().FillOff().Group(g).GroupSep(s));
|
||||||
}
|
}
|
||||||
template<int width, typename T>
|
template<int width, typename T>
|
||||||
static inline Tstring dec0(unsigned int g, char s, const T& x)
|
static inline Tstring dec0(unsigned int g, char s, const T& x)
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(std::numeric_limits<T>::is_integer);
|
static_assert(std::numeric_limits<T>::is_integer);
|
||||||
return FormatValTFunctor<Tstring>()(x, FormatSpec().BaseDec().FillNul().Width(width).Group(g).GroupSep(s));
|
return FormatValTFunctor<Tstring>()(x, FormatSpec().BaseDec().FillNul().Width(width).Group(g).GroupSep(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static inline Tstring hex(const T& x)
|
static inline Tstring hex(const T& x)
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(std::numeric_limits<T>::is_integer);
|
static_assert(std::numeric_limits<T>::is_integer);
|
||||||
return FormatValTFunctor<Tstring>()(x, FormatSpec().BaseHex().CaseLow().FillOff());
|
return FormatValTFunctor<Tstring>()(x, FormatSpec().BaseHex().CaseLow().FillOff());
|
||||||
}
|
}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static inline Tstring HEX(const T& x)
|
static inline Tstring HEX(const T& x)
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(std::numeric_limits<T>::is_integer);
|
static_assert(std::numeric_limits<T>::is_integer);
|
||||||
return FormatValTFunctor<Tstring>()(x, FormatSpec().BaseHex().CaseUpp().FillOff());
|
return FormatValTFunctor<Tstring>()(x, FormatSpec().BaseHex().CaseUpp().FillOff());
|
||||||
}
|
}
|
||||||
template<int width, typename T>
|
template<int width, typename T>
|
||||||
static inline Tstring hex0(const T& x)
|
static inline Tstring hex0(const T& x)
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(std::numeric_limits<T>::is_integer);
|
static_assert(std::numeric_limits<T>::is_integer);
|
||||||
return FormatValTFunctor<Tstring>()(x, FormatSpec().BaseHex().CaseLow().FillNul().Width(width));
|
return FormatValTFunctor<Tstring>()(x, FormatSpec().BaseHex().CaseLow().FillNul().Width(width));
|
||||||
}
|
}
|
||||||
template<int width, typename T>
|
template<int width, typename T>
|
||||||
static inline Tstring HEX0(const T& x)
|
static inline Tstring HEX0(const T& x)
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(std::numeric_limits<T>::is_integer);
|
static_assert(std::numeric_limits<T>::is_integer);
|
||||||
return FormatValTFunctor<Tstring>()(x, FormatSpec().BaseHex().CaseUpp().FillNul().Width(width));
|
return FormatValTFunctor<Tstring>()(x, FormatSpec().BaseHex().CaseUpp().FillNul().Width(width));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static inline Tstring hex(unsigned int g, char s, const T& x)
|
static inline Tstring hex(unsigned int g, char s, const T& x)
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(std::numeric_limits<T>::is_integer);
|
static_assert(std::numeric_limits<T>::is_integer);
|
||||||
return FormatValTFunctor<Tstring>()(x, FormatSpec().BaseHex().CaseLow().FillOff().Group(g).GroupSep(s));
|
return FormatValTFunctor<Tstring>()(x, FormatSpec().BaseHex().CaseLow().FillOff().Group(g).GroupSep(s));
|
||||||
}
|
}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static inline Tstring HEX(unsigned int g, char s, const T& x)
|
static inline Tstring HEX(unsigned int g, char s, const T& x)
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(std::numeric_limits<T>::is_integer);
|
static_assert(std::numeric_limits<T>::is_integer);
|
||||||
return FormatValTFunctor<Tstring>()(x, FormatSpec().BaseHex().CaseUpp().FillOff().Group(g).GroupSep(s));
|
return FormatValTFunctor<Tstring>()(x, FormatSpec().BaseHex().CaseUpp().FillOff().Group(g).GroupSep(s));
|
||||||
}
|
}
|
||||||
template<int width, typename T>
|
template<int width, typename T>
|
||||||
static inline Tstring hex0(unsigned int g, char s, const T& x)
|
static inline Tstring hex0(unsigned int g, char s, const T& x)
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(std::numeric_limits<T>::is_integer);
|
static_assert(std::numeric_limits<T>::is_integer);
|
||||||
return FormatValTFunctor<Tstring>()(x, FormatSpec().BaseHex().CaseLow().FillNul().Width(width).Group(g).GroupSep(s));
|
return FormatValTFunctor<Tstring>()(x, FormatSpec().BaseHex().CaseLow().FillNul().Width(width).Group(g).GroupSep(s));
|
||||||
}
|
}
|
||||||
template<int width, typename T>
|
template<int width, typename T>
|
||||||
static inline Tstring HEX0(unsigned int g, char s, const T& x)
|
static inline Tstring HEX0(unsigned int g, char s, const T& x)
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(std::numeric_limits<T>::is_integer);
|
static_assert(std::numeric_limits<T>::is_integer);
|
||||||
return FormatValTFunctor<Tstring>()(x, FormatSpec().BaseHex().CaseUpp().FillNul().Width(width).Group(g).GroupSep(s));
|
return FormatValTFunctor<Tstring>()(x, FormatSpec().BaseHex().CaseUpp().FillNul().Width(width).Group(g).GroupSep(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static inline Tstring flt(const T& x, int precision = -1)
|
static inline Tstring flt(const T& x, int precision = -1)
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(std::is_floating_point<T>::value);
|
static_assert(std::is_floating_point<T>::value);
|
||||||
return FormatValTFunctor<Tstring>()(x, FormatSpec().NotaNrm().FillOff().Precision(precision));
|
return FormatValTFunctor<Tstring>()(x, FormatSpec().NotaNrm().FillOff().Precision(precision));
|
||||||
}
|
}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static inline Tstring fix(const T& x, int precision = -1)
|
static inline Tstring fix(const T& x, int precision = -1)
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(std::is_floating_point<T>::value);
|
static_assert(std::is_floating_point<T>::value);
|
||||||
return FormatValTFunctor<Tstring>()(x, FormatSpec().NotaFix().FillOff().Precision(precision));
|
return FormatValTFunctor<Tstring>()(x, FormatSpec().NotaFix().FillOff().Precision(precision));
|
||||||
}
|
}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static inline Tstring sci(const T& x, int precision = -1)
|
static inline Tstring sci(const T& x, int precision = -1)
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(std::is_floating_point<T>::value);
|
static_assert(std::is_floating_point<T>::value);
|
||||||
return FormatValTFunctor<Tstring>()(x, FormatSpec().NotaSci().FillOff().Precision(precision));
|
return FormatValTFunctor<Tstring>()(x, FormatSpec().NotaSci().FillOff().Precision(precision));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static inline Tstring ptr(const T& x)
|
||||||
|
{
|
||||||
|
static_assert(std::is_pointer<T>::value || std::is_same<T, std::uintptr_t>::value || std::is_same<T, std::intptr_t>::value, "");
|
||||||
|
return hex0<mpt::pointer_size * 2>(pointer_cast<const std::uintptr_t>(x));
|
||||||
|
}
|
||||||
|
template<typename T>
|
||||||
|
static inline Tstring PTR(const T& x)
|
||||||
|
{
|
||||||
|
static_assert(std::is_pointer<T>::value || std::is_same<T, std::uintptr_t>::value || std::is_same<T, std::intptr_t>::value, "");
|
||||||
|
return HEX0<mpt::pointer_size * 2>(pointer_cast<const std::uintptr_t>(x));
|
||||||
|
}
|
||||||
|
|
||||||
static inline Tstring pad_left(std::size_t width_, const Tstring &str)
|
static inline Tstring pad_left(std::size_t width_, const Tstring &str)
|
||||||
{
|
{
|
||||||
typedef mpt::string_traits<Tstring> traits;
|
typedef mpt::string_traits<Tstring> traits;
|
||||||
|
@ -514,9 +549,9 @@ typedef fmtT<mpt::lstring> lfmt;
|
||||||
#if MPT_OS_WINDOWS
|
#if MPT_OS_WINDOWS
|
||||||
typedef fmtT<mpt::tstring> tfmt;
|
typedef fmtT<mpt::tstring> tfmt;
|
||||||
#endif
|
#endif
|
||||||
#if defined(_MFC_VER)
|
#if defined(MPT_WITH_MFC)
|
||||||
typedef fmtT<CString> cfmt;
|
typedef fmtT<CString> cfmt;
|
||||||
#endif
|
#endif // MPT_WITH_MFC
|
||||||
|
|
||||||
} // namespace mpt
|
} // namespace mpt
|
||||||
|
|
||||||
|
@ -546,305 +581,117 @@ template <> struct to_string_type<mpt::ustring > { typedef mpt::ustring type;
|
||||||
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
||||||
template <> struct to_string_type<mpt::lstring > { typedef mpt::lstring type; };
|
template <> struct to_string_type<mpt::lstring > { typedef mpt::lstring type; };
|
||||||
#endif // MPT_ENABLE_CHARSET_LOCALE
|
#endif // MPT_ENABLE_CHARSET_LOCALE
|
||||||
#if defined(_MFC_VER)
|
#if defined(MPT_WITH_MFC)
|
||||||
template <> struct to_string_type<CString > { typedef CString type; };
|
template <> struct to_string_type<CString > { typedef CString type; };
|
||||||
#endif
|
#endif // MPT_WITH_MFC
|
||||||
template <typename T, std::size_t N> struct to_string_type<T [N]> { typedef typename to_string_type<T>::type type; };
|
template <typename T, std::size_t N> struct to_string_type<T [N]> { typedef typename to_string_type<T>::type type; };
|
||||||
|
|
||||||
std::string PrintImpl(const std::string & format
|
|
||||||
, const std::string & x1 = std::string()
|
|
||||||
, const std::string & x2 = std::string()
|
|
||||||
, const std::string & x3 = std::string()
|
|
||||||
, const std::string & x4 = std::string()
|
|
||||||
, const std::string & x5 = std::string()
|
|
||||||
, const std::string & x6 = std::string()
|
|
||||||
, const std::string & x7 = std::string()
|
|
||||||
, const std::string & x8 = std::string()
|
|
||||||
);
|
|
||||||
|
|
||||||
#if MPT_WSTRING_FORMAT
|
|
||||||
std::wstring PrintImpl(const std::wstring & format
|
|
||||||
, const std::wstring & x1 = std::wstring()
|
|
||||||
, const std::wstring & x2 = std::wstring()
|
|
||||||
, const std::wstring & x3 = std::wstring()
|
|
||||||
, const std::wstring & x4 = std::wstring()
|
|
||||||
, const std::wstring & x5 = std::wstring()
|
|
||||||
, const std::wstring & x6 = std::wstring()
|
|
||||||
, const std::wstring & x7 = std::wstring()
|
|
||||||
, const std::wstring & x8 = std::wstring()
|
|
||||||
);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if MPT_USTRING_MODE_UTF8
|
|
||||||
mpt::ustring PrintImpl(const mpt::ustring & format
|
|
||||||
, const mpt::ustring & x1 = mpt::ustring()
|
|
||||||
, const mpt::ustring & x2 = mpt::ustring()
|
|
||||||
, const mpt::ustring & x3 = mpt::ustring()
|
|
||||||
, const mpt::ustring & x4 = mpt::ustring()
|
|
||||||
, const mpt::ustring & x5 = mpt::ustring()
|
|
||||||
, const mpt::ustring & x6 = mpt::ustring()
|
|
||||||
, const mpt::ustring & x7 = mpt::ustring()
|
|
||||||
, const mpt::ustring & x8 = mpt::ustring()
|
|
||||||
);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
|
||||||
mpt::lstring PrintImpl(const mpt::lstring & format
|
|
||||||
, const mpt::lstring & x1 = mpt::lstring()
|
|
||||||
, const mpt::lstring & x2 = mpt::lstring()
|
|
||||||
, const mpt::lstring & x3 = mpt::lstring()
|
|
||||||
, const mpt::lstring & x4 = mpt::lstring()
|
|
||||||
, const mpt::lstring & x5 = mpt::lstring()
|
|
||||||
, const mpt::lstring & x6 = mpt::lstring()
|
|
||||||
, const mpt::lstring & x7 = mpt::lstring()
|
|
||||||
, const mpt::lstring & x8 = mpt::lstring()
|
|
||||||
);
|
|
||||||
#endif // MPT_ENABLE_CHARSET_LOCALE
|
|
||||||
|
|
||||||
#if defined(_MFC_VER)
|
|
||||||
CString PrintImpl(const CString & format
|
|
||||||
, const CString & x1 = CString()
|
|
||||||
, const CString & x2 = CString()
|
|
||||||
, const CString & x3 = CString()
|
|
||||||
, const CString & x4 = CString()
|
|
||||||
, const CString & x5 = CString()
|
|
||||||
, const CString & x6 = CString()
|
|
||||||
, const CString & x7 = CString()
|
|
||||||
, const CString & x8 = CString()
|
|
||||||
);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
} // namespace String
|
} // namespace String
|
||||||
|
|
||||||
template<typename Tformat>
|
template<typename Tformat>
|
||||||
struct message_formatter
|
class message_formatter
|
||||||
{
|
{
|
||||||
typedef typename mpt::String::detail::to_string_type<Tformat>::type Tstring;
|
|
||||||
Tstring format;
|
|
||||||
message_formatter(const Tstring & format) : format(format) {}
|
|
||||||
|
|
||||||
Tstring operator() (
|
public:
|
||||||
) const
|
|
||||||
{
|
|
||||||
return mpt::String::detail::PrintImpl(format
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<
|
typedef typename mpt::String::detail::to_string_type<Tformat>::type Tstring;
|
||||||
typename T1
|
|
||||||
>
|
|
||||||
Tstring operator() (
|
|
||||||
const T1& x1
|
|
||||||
) const {
|
|
||||||
return mpt::String::detail::PrintImpl(format
|
|
||||||
, ToStringTFunctor<Tstring>()(x1)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<
|
private:
|
||||||
typename T1
|
|
||||||
, typename T2
|
|
||||||
>
|
|
||||||
Tstring operator() (
|
|
||||||
const T1& x1
|
|
||||||
, const T2& x2
|
|
||||||
) const {
|
|
||||||
return mpt::String::detail::PrintImpl(format
|
|
||||||
, ToStringTFunctor<Tstring>()(x1)
|
|
||||||
, ToStringTFunctor<Tstring>()(x2)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<
|
Tstring format;
|
||||||
typename T1
|
|
||||||
, typename T2
|
|
||||||
, typename T3
|
|
||||||
>
|
|
||||||
Tstring operator() (
|
|
||||||
const T1& x1
|
|
||||||
, const T2& x2
|
|
||||||
, const T3& x3
|
|
||||||
) const {
|
|
||||||
return mpt::String::detail::PrintImpl(format
|
|
||||||
, ToStringTFunctor<Tstring>()(x1)
|
|
||||||
, ToStringTFunctor<Tstring>()(x2)
|
|
||||||
, ToStringTFunctor<Tstring>()(x3)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<
|
private:
|
||||||
typename T1
|
|
||||||
, typename T2
|
|
||||||
, typename T3
|
|
||||||
, typename T4
|
|
||||||
>
|
|
||||||
Tstring operator() (
|
|
||||||
const T1& x1
|
|
||||||
, const T2& x2
|
|
||||||
, const T3& x3
|
|
||||||
, const T4& x4
|
|
||||||
) const {
|
|
||||||
return mpt::String::detail::PrintImpl(format
|
|
||||||
, ToStringTFunctor<Tstring>()(x1)
|
|
||||||
, ToStringTFunctor<Tstring>()(x2)
|
|
||||||
, ToStringTFunctor<Tstring>()(x3)
|
|
||||||
, ToStringTFunctor<Tstring>()(x4)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<
|
MPT_NOINLINE Tstring do_format(mpt::span<const Tstring> vals) const
|
||||||
typename T1
|
{
|
||||||
, typename T2
|
typedef typename mpt::string_traits<Tstring> traits;
|
||||||
, typename T3
|
Tstring result;
|
||||||
, typename T4
|
const typename traits::size_type len = traits::length(format);
|
||||||
, typename T5
|
traits::reserve(result, len);
|
||||||
>
|
for(typename traits::size_type pos = 0; pos != len; ++pos)
|
||||||
Tstring operator() (
|
{
|
||||||
const T1& x1
|
typename traits::char_type c = format[pos];
|
||||||
, const T2& x2
|
if(pos + 1 != len && c == typename traits::char_type('%'))
|
||||||
, const T3& x3
|
{
|
||||||
, const T4& x4
|
pos++;
|
||||||
, const T5& x5
|
c = format[pos];
|
||||||
) const {
|
if(typename traits::char_type('1') <= c && c <= typename traits::char_type('9'))
|
||||||
return mpt::String::detail::PrintImpl(format
|
{
|
||||||
, ToStringTFunctor<Tstring>()(x1)
|
const std::size_t n = c - typename traits::char_type('0') - 1;
|
||||||
, ToStringTFunctor<Tstring>()(x2)
|
if(n < std::size(vals))
|
||||||
, ToStringTFunctor<Tstring>()(x3)
|
{
|
||||||
, ToStringTFunctor<Tstring>()(x4)
|
traits::append(result, vals[n]);
|
||||||
, ToStringTFunctor<Tstring>()(x5)
|
}
|
||||||
);
|
continue;
|
||||||
}
|
} else if(c != typename traits::char_type('%'))
|
||||||
|
{
|
||||||
|
traits::append(result, 1, typename traits::char_type('%'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
traits::append(result, 1, c);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
template<
|
public:
|
||||||
typename T1
|
|
||||||
, typename T2
|
|
||||||
, typename T3
|
|
||||||
, typename T4
|
|
||||||
, typename T5
|
|
||||||
, typename T6
|
|
||||||
>
|
|
||||||
Tstring operator() (
|
|
||||||
const T1& x1
|
|
||||||
, const T2& x2
|
|
||||||
, const T3& x3
|
|
||||||
, const T4& x4
|
|
||||||
, const T5& x5
|
|
||||||
, const T6& x6
|
|
||||||
) const {
|
|
||||||
return mpt::String::detail::PrintImpl(format
|
|
||||||
, ToStringTFunctor<Tstring>()(x1)
|
|
||||||
, ToStringTFunctor<Tstring>()(x2)
|
|
||||||
, ToStringTFunctor<Tstring>()(x3)
|
|
||||||
, ToStringTFunctor<Tstring>()(x4)
|
|
||||||
, ToStringTFunctor<Tstring>()(x5)
|
|
||||||
, ToStringTFunctor<Tstring>()(x6)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<
|
message_formatter(Tstring format_)
|
||||||
typename T1
|
: format(std::move(format_))
|
||||||
, typename T2
|
{
|
||||||
, typename T3
|
}
|
||||||
, typename T4
|
|
||||||
, typename T5
|
|
||||||
, typename T6
|
|
||||||
, typename T7
|
|
||||||
>
|
|
||||||
Tstring operator() (
|
|
||||||
const T1& x1
|
|
||||||
, const T2& x2
|
|
||||||
, const T3& x3
|
|
||||||
, const T4& x4
|
|
||||||
, const T5& x5
|
|
||||||
, const T6& x6
|
|
||||||
, const T7& x7
|
|
||||||
) const {
|
|
||||||
return mpt::String::detail::PrintImpl(format
|
|
||||||
, ToStringTFunctor<Tstring>()(x1)
|
|
||||||
, ToStringTFunctor<Tstring>()(x2)
|
|
||||||
, ToStringTFunctor<Tstring>()(x3)
|
|
||||||
, ToStringTFunctor<Tstring>()(x4)
|
|
||||||
, ToStringTFunctor<Tstring>()(x5)
|
|
||||||
, ToStringTFunctor<Tstring>()(x6)
|
|
||||||
, ToStringTFunctor<Tstring>()(x7)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<
|
public:
|
||||||
typename T1
|
|
||||||
, typename T2
|
template<typename ...Ts>
|
||||||
, typename T3
|
Tstring operator() (const Ts&... xs) const
|
||||||
, typename T4
|
{
|
||||||
, typename T5
|
const std::array<Tstring, sizeof...(xs)> vals{{ToStringTFunctor<Tstring>()(xs)...}};
|
||||||
, typename T6
|
return do_format(mpt::as_span(vals));
|
||||||
, typename T7
|
}
|
||||||
, typename T8
|
|
||||||
>
|
|
||||||
Tstring operator() (
|
|
||||||
const T1& x1
|
|
||||||
, const T2& x2
|
|
||||||
, const T3& x3
|
|
||||||
, const T4& x4
|
|
||||||
, const T5& x5
|
|
||||||
, const T6& x6
|
|
||||||
, const T7& x7
|
|
||||||
, const T8& x8
|
|
||||||
) const {
|
|
||||||
return mpt::String::detail::PrintImpl(format
|
|
||||||
, ToStringTFunctor<Tstring>()(x1)
|
|
||||||
, ToStringTFunctor<Tstring>()(x2)
|
|
||||||
, ToStringTFunctor<Tstring>()(x3)
|
|
||||||
, ToStringTFunctor<Tstring>()(x4)
|
|
||||||
, ToStringTFunctor<Tstring>()(x5)
|
|
||||||
, ToStringTFunctor<Tstring>()(x6)
|
|
||||||
, ToStringTFunctor<Tstring>()(x7)
|
|
||||||
, ToStringTFunctor<Tstring>()(x8)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}; // struct message_formatter<Tformat>
|
}; // struct message_formatter<Tformat>
|
||||||
|
|
||||||
template<typename Tformat>
|
template<typename Tformat>
|
||||||
message_formatter<typename mpt::String::detail::to_string_type<Tformat>::type> format(const Tformat &format)
|
message_formatter<typename mpt::String::detail::to_string_type<Tformat>::type> format(Tformat format)
|
||||||
{
|
{
|
||||||
typedef typename mpt::String::detail::to_string_type<Tformat>::type Tstring;
|
typedef typename mpt::String::detail::to_string_type<Tformat>::type Tstring;
|
||||||
return message_formatter<Tstring>(Tstring(format));
|
return message_formatter<Tstring>(Tstring(std::move(format)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MPT_WSTRING_FORMAT
|
#if MPT_WSTRING_FORMAT
|
||||||
static inline message_formatter<std::wstring> wformat(const std::wstring &format)
|
static inline message_formatter<std::wstring> wformat(std::wstring format)
|
||||||
{
|
{
|
||||||
return message_formatter<std::wstring>(format);
|
return message_formatter<std::wstring>(std::move(format));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static inline message_formatter<mpt::ustring> uformat(const mpt::ustring &format)
|
static inline message_formatter<mpt::ustring> uformat(mpt::ustring format)
|
||||||
{
|
{
|
||||||
return message_formatter<mpt::ustring>(format);
|
return message_formatter<mpt::ustring>(std::move(format));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
||||||
static inline message_formatter<mpt::lstring> lformat(const mpt::lstring &format)
|
static inline message_formatter<mpt::lstring> lformat(mpt::lstring format)
|
||||||
{
|
{
|
||||||
return message_formatter<mpt::lstring>(format);
|
return message_formatter<mpt::lstring>(std::move(format));
|
||||||
}
|
}
|
||||||
#endif // MPT_ENABLE_CHARSET_LOCALE
|
#endif // MPT_ENABLE_CHARSET_LOCALE
|
||||||
|
|
||||||
#if MPT_OS_WINDOWS
|
#if MPT_OS_WINDOWS
|
||||||
static inline message_formatter<mpt::tstring> tformat(const mpt::tstring &format)
|
static inline message_formatter<mpt::tstring> tformat(mpt::tstring format)
|
||||||
{
|
{
|
||||||
return message_formatter<mpt::tstring>(format);
|
return message_formatter<mpt::tstring>(std::move(format));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_MFC_VER)
|
#if defined(MPT_WITH_MFC)
|
||||||
static inline message_formatter<CString> cformat(const CString &format)
|
static inline message_formatter<CString> cformat(CString format)
|
||||||
{
|
{
|
||||||
return message_formatter<CString>(format);
|
return message_formatter<CString>(std::move(format));
|
||||||
}
|
}
|
||||||
#endif
|
#endif // MPT_WITH_MFC
|
||||||
|
|
||||||
} // namespace mpt
|
} // namespace mpt
|
||||||
|
|
||||||
|
|
|
@ -80,19 +80,19 @@ template<> inline double ConvertStrTo(const std::wstring &str) { return ConvertS
|
||||||
template<> inline long double ConvertStrTo(const std::wstring &str) { return ConvertStrToLongDouble(str); }
|
template<> inline long double ConvertStrTo(const std::wstring &str) { return ConvertStrToLongDouble(str); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_MFC_VER)
|
#if defined(MPT_WITH_MFC)
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline T ConvertStrTo(const CString &str)
|
inline T ConvertStrTo(const CString &str)
|
||||||
{
|
{
|
||||||
#if defined(UNICODE) && MPT_WSTRING_FORMAT
|
#if defined(UNICODE) && MPT_WSTRING_FORMAT
|
||||||
return ConvertStrTo<T>(mpt::ToWide(str));
|
return ConvertStrTo<T>(mpt::ToWide(str));
|
||||||
#elif defined(UNICODE)
|
#elif defined(UNICODE)
|
||||||
return ConvertStrTo<T>(mpt::ToCharset(mpt::CharsetUTF8, str));
|
return ConvertStrTo<T>(mpt::ToCharset(mpt::Charset::UTF8, str));
|
||||||
#else // !UNICODE
|
#else // !UNICODE
|
||||||
return ConvertStrTo<T>(mpt::ToCharset(mpt::CharsetLocale, str));
|
return ConvertStrTo<T>(mpt::ToCharset(mpt::Charset::Locale, str));
|
||||||
#endif // UNICODE
|
#endif // UNICODE
|
||||||
}
|
}
|
||||||
#endif // _MFC_VER
|
#endif // MPT_WITH_MFC
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline T ConvertStrTo(const char *str)
|
inline T ConvertStrTo(const char *str)
|
||||||
|
@ -123,7 +123,7 @@ inline T ConvertStrTo(const wchar_t *str)
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline T ConvertStrTo(const mpt::ustring &str)
|
inline T ConvertStrTo(const mpt::ustring &str)
|
||||||
{
|
{
|
||||||
return ConvertStrTo<T>(mpt::ToCharset(mpt::CharsetUTF8, str));
|
return ConvertStrTo<T>(mpt::ToCharset(mpt::Charset::UTF8, str));
|
||||||
}
|
}
|
||||||
template<> inline mpt::ustring ConvertStrTo(const mpt::ustring &str) { return str; }
|
template<> inline mpt::ustring ConvertStrTo(const mpt::ustring &str) { return str; }
|
||||||
#if MPT_WSTRING_CONVERT
|
#if MPT_WSTRING_CONVERT
|
||||||
|
@ -135,7 +135,7 @@ template<> inline std::wstring ConvertStrTo(const mpt::ustring &str) { return mp
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline T ConvertStrTo(const mpt::lstring &str)
|
inline T ConvertStrTo(const mpt::lstring &str)
|
||||||
{
|
{
|
||||||
return ConvertStrTo<T>(mpt::ToCharset(mpt::CharsetLocale, str));
|
return ConvertStrTo<T>(mpt::ToCharset(mpt::Charset::Locale, str));
|
||||||
}
|
}
|
||||||
template<> inline mpt::lstring ConvertStrTo(const mpt::lstring &str) { return str; }
|
template<> inline mpt::lstring ConvertStrTo(const mpt::lstring &str) { return str; }
|
||||||
#endif
|
#endif
|
||||||
|
@ -176,7 +176,7 @@ inline T Hex(const char *str)
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline T Hex(const std::wstring &str)
|
inline T Hex(const std::wstring &str)
|
||||||
{
|
{
|
||||||
return Hex<T>(mpt::ToCharset(mpt::CharsetUTF8, str));
|
return Hex<T>(mpt::ToCharset(mpt::Charset::UTF8, str));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -195,7 +195,7 @@ inline T Hex(const wchar_t *str)
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline T Hex(const mpt::ustring &str)
|
inline T Hex(const mpt::ustring &str)
|
||||||
{
|
{
|
||||||
return Hex<T>(mpt::ToCharset(mpt::CharsetUTF8, str));
|
return Hex<T>(mpt::ToCharset(mpt::Charset::UTF8, str));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -104,6 +104,18 @@ public:
|
||||||
DWORD dummy = 0; // For Win9x
|
DWORD dummy = 0; // For Win9x
|
||||||
threadHandle = CreateThread(NULL, 0, function, userData, 0, &dummy);
|
threadHandle = CreateThread(NULL, 0, function, userData, 0, &dummy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UnmanagedThread(UnmanagedThread &&) = default;
|
||||||
|
UnmanagedThread & operator=(UnmanagedThread &&) = default;
|
||||||
|
|
||||||
|
UnmanagedThread(const UnmanagedThread &) = delete;
|
||||||
|
UnmanagedThread & operator=(const UnmanagedThread &) = delete;
|
||||||
|
|
||||||
|
// unmanaged, user has to free resources
|
||||||
|
~UnmanagedThread()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Thread that operates on a member function
|
// Thread that operates on a member function
|
||||||
|
|
|
@ -47,7 +47,7 @@ uint64 Now()
|
||||||
|
|
||||||
mpt::ustring ToUString(uint64 time100ns)
|
mpt::ustring ToUString(uint64 time100ns)
|
||||||
{
|
{
|
||||||
static const std::size_t bufsize = 256;
|
constexpr std::size_t bufsize = 256;
|
||||||
|
|
||||||
mpt::ustring result;
|
mpt::ustring result;
|
||||||
|
|
||||||
|
@ -233,7 +233,7 @@ void MultimediaClock::SetPeriod(uint32 ms)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ms = mpt::clamp<uint32>(ms, caps.wPeriodMin, caps.wPeriodMax);
|
ms = std::clamp(mpt::saturate_cast<UINT>(ms), caps.wPeriodMin, caps.wPeriodMax);
|
||||||
if(timeBeginPeriod(ms) != MMSYSERR_NOERROR)
|
if(timeBeginPeriod(ms) != MMSYSERR_NOERROR)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -20,9 +20,9 @@
|
||||||
#if MPT_OS_WINDOWS
|
#if MPT_OS_WINDOWS
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <rpc.h>
|
#include <rpc.h>
|
||||||
#if defined(MODPLUG_TRACKER) || !defined(NO_DMO) || MPT_OS_WINDOWS_WINRT
|
#if defined(MODPLUG_TRACKER) || defined(MPT_WITH_DMO) || MPT_OS_WINDOWS_WINRT
|
||||||
#include <objbase.h>
|
#include <objbase.h>
|
||||||
#endif // MODPLUG_TRACKER || !NO_DMO || MPT_OS_WINDOWS_WINRT
|
#endif // MODPLUG_TRACKER || MPT_WITH_DMO || MPT_OS_WINDOWS_WINRT
|
||||||
#endif // MPT_OS_WINDOWS
|
#endif // MPT_OS_WINDOWS
|
||||||
|
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ namespace Util
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
#if defined(MODPLUG_TRACKER) || !defined(NO_DMO)
|
#if defined(MODPLUG_TRACKER) || defined(MPT_WITH_DMO)
|
||||||
|
|
||||||
|
|
||||||
mpt::winstring CLSIDToString(CLSID clsid)
|
mpt::winstring CLSIDToString(CLSID clsid)
|
||||||
|
@ -298,7 +298,7 @@ bool IsValid(UUID uuid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif // MODPLUG_TRACKER || !NO_DMO
|
#endif // MODPLUG_TRACKER || MPT_WITH_DMO
|
||||||
|
|
||||||
|
|
||||||
} // namespace Util
|
} // namespace Util
|
||||||
|
@ -348,7 +348,7 @@ mpt::UUID UUIDFromWin32(::UUID uuid)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(MODPLUG_TRACKER) || !defined(NO_DMO)
|
#if defined(MODPLUG_TRACKER) || defined(MPT_WITH_DMO)
|
||||||
|
|
||||||
UUID::UUID(::UUID uuid)
|
UUID::UUID(::UUID uuid)
|
||||||
{
|
{
|
||||||
|
@ -360,7 +360,7 @@ UUID::operator ::UUID () const
|
||||||
return UUIDToWin32(*this);
|
return UUIDToWin32(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // MODPLUG_TRACKER || !NO_DMO
|
#endif // MODPLUG_TRACKER || MPT_WITH_DMO
|
||||||
|
|
||||||
#endif // MPT_OS_WINDOWS
|
#endif // MPT_OS_WINDOWS
|
||||||
|
|
||||||
|
@ -535,6 +535,7 @@ UUID::UUID(GUIDms guid)
|
||||||
UUID::operator UUIDbin() const
|
UUID::operator UUIDbin() const
|
||||||
{
|
{
|
||||||
UUIDbin result;
|
UUIDbin result;
|
||||||
|
Clear(result);
|
||||||
result.Data1 = GetData1();
|
result.Data1 = GetData1();
|
||||||
result.Data2 = GetData2();
|
result.Data2 = GetData2();
|
||||||
result.Data3 = GetData3();
|
result.Data3 = GetData3();
|
||||||
|
@ -545,6 +546,7 @@ UUID::operator UUIDbin() const
|
||||||
UUID::operator GUIDms() const
|
UUID::operator GUIDms() const
|
||||||
{
|
{
|
||||||
GUIDms result;
|
GUIDms result;
|
||||||
|
Clear(result);
|
||||||
result.Data1 = GetData1();
|
result.Data1 = GetData1();
|
||||||
result.Data2 = GetData2();
|
result.Data2 = GetData2();
|
||||||
result.Data3 = GetData3();
|
result.Data3 = GetData3();
|
||||||
|
|
|
@ -15,11 +15,13 @@
|
||||||
|
|
||||||
#include "Endianness.h"
|
#include "Endianness.h"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
#if MPT_OS_WINDOWS
|
#if MPT_OS_WINDOWS
|
||||||
#if defined(MODPLUG_TRACKER) || !defined(NO_DMO)
|
#if defined(MODPLUG_TRACKER) || defined(MPT_WITH_DMO)
|
||||||
#include <guiddef.h>
|
#include <guiddef.h>
|
||||||
#include <rpc.h>
|
#include <rpc.h>
|
||||||
#endif // MODPLUG_TRACKER || !NO_DMO
|
#endif // MODPLUG_TRACKER || MPT_WITH_DMO
|
||||||
#endif // MPT_OS_WINDOWS
|
#endif // MPT_OS_WINDOWS
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,7 +32,7 @@ OPENMPT_NAMESPACE_BEGIN
|
||||||
namespace Util
|
namespace Util
|
||||||
{
|
{
|
||||||
|
|
||||||
#if defined(MODPLUG_TRACKER) || !defined(NO_DMO)
|
#if defined(MODPLUG_TRACKER) || defined(MPT_WITH_DMO)
|
||||||
|
|
||||||
// COM CLSID<->string conversion
|
// COM CLSID<->string conversion
|
||||||
// A CLSID string is not necessarily a standard UUID string,
|
// A CLSID string is not necessarily a standard UUID string,
|
||||||
|
@ -56,7 +58,7 @@ GUID CreateGUID();
|
||||||
// Checks the UUID against the NULL UUID. Returns false if it is NULL, true otherwise.
|
// Checks the UUID against the NULL UUID. Returns false if it is NULL, true otherwise.
|
||||||
bool IsValid(UUID uuid);
|
bool IsValid(UUID uuid);
|
||||||
|
|
||||||
#endif // MODPLUG_TRACKER || !NO_DMO
|
#endif // MODPLUG_TRACKER || MPT_WITH_DMO
|
||||||
|
|
||||||
} // namespace Util
|
} // namespace Util
|
||||||
|
|
||||||
|
@ -96,6 +98,9 @@ public:
|
||||||
MPT_CONSTEXPR11_FUN uint16 GetData2() const noexcept { return Data2; }
|
MPT_CONSTEXPR11_FUN uint16 GetData2() const noexcept { return Data2; }
|
||||||
MPT_CONSTEXPR11_FUN uint16 GetData3() const noexcept { return Data3; }
|
MPT_CONSTEXPR11_FUN uint16 GetData3() const noexcept { return Data3; }
|
||||||
MPT_CONSTEXPR11_FUN uint64 GetData4() const noexcept { return Data4; }
|
MPT_CONSTEXPR11_FUN uint64 GetData4() const noexcept { return Data4; }
|
||||||
|
public:
|
||||||
|
MPT_CONSTEXPR11_FUN uint64 GetData64_1() const noexcept { return (static_cast<uint64>(Data1) << 32) | (static_cast<uint64>(Data2) << 16) | (static_cast<uint64>(Data3) << 0); }
|
||||||
|
MPT_CONSTEXPR11_FUN uint64 GetData64_2() const noexcept { return Data4; }
|
||||||
public:
|
public:
|
||||||
// xxxxxxxx-xxxx-Mmxx-Nnxx-xxxxxxxxxxxx
|
// xxxxxxxx-xxxx-Mmxx-Nnxx-xxxxxxxxxxxx
|
||||||
// <--32-->-<16>-<16>-<-------64------>
|
// <--32-->-<16>-<16>-<-------64------>
|
||||||
|
@ -109,10 +114,10 @@ private:
|
||||||
MPT_CONSTEXPR11_FUN uint8 Nn() const noexcept { return static_cast<uint8>((Data4 >> 56) & 0xffu); }
|
MPT_CONSTEXPR11_FUN uint8 Nn() const noexcept { return static_cast<uint8>((Data4 >> 56) & 0xffu); }
|
||||||
void MakeRFC4122(uint8 version) noexcept;
|
void MakeRFC4122(uint8 version) noexcept;
|
||||||
public:
|
public:
|
||||||
#if MPT_OS_WINDOWS && (defined(MODPLUG_TRACKER) || !defined(NO_DMO))
|
#if MPT_OS_WINDOWS && (defined(MODPLUG_TRACKER) || defined(MPT_WITH_DMO))
|
||||||
explicit UUID(::UUID uuid);
|
explicit UUID(::UUID uuid);
|
||||||
operator ::UUID () const;
|
operator ::UUID () const;
|
||||||
#endif // MPT_OS_WINDOWS && (MODPLUG_TRACKER || !NO_DMO)
|
#endif // MPT_OS_WINDOWS && (MODPLUG_TRACKER || MPT_WITH_DMO)
|
||||||
private:
|
private:
|
||||||
static MPT_CONSTEXPR11_FUN uint8 NibbleFromChar(char x)
|
static MPT_CONSTEXPR11_FUN uint8 NibbleFromChar(char x)
|
||||||
{
|
{
|
||||||
|
@ -120,7 +125,7 @@ private:
|
||||||
('0' <= x && x <= '9') ? static_cast<uint8>(x - '0' + 0) :
|
('0' <= x && x <= '9') ? static_cast<uint8>(x - '0' + 0) :
|
||||||
('a' <= x && x <= 'z') ? static_cast<uint8>(x - 'a' + 10) :
|
('a' <= x && x <= 'z') ? static_cast<uint8>(x - 'a' + 10) :
|
||||||
('A' <= x && x <= 'Z') ? static_cast<uint8>(x - 'A' + 10) :
|
('A' <= x && x <= 'Z') ? static_cast<uint8>(x - 'A' + 10) :
|
||||||
throw std::domain_error("");
|
mpt::constexpr_throw<uint8>(std::domain_error(""));
|
||||||
}
|
}
|
||||||
static MPT_CONSTEXPR11_FUN uint8 ByteFromHex(char x, char y)
|
static MPT_CONSTEXPR11_FUN uint8 ByteFromHex(char x, char y)
|
||||||
{
|
{
|
||||||
|
@ -159,7 +164,7 @@ public:
|
||||||
| (static_cast<uint64>(ParseHex16(str + 24)) << 32)
|
| (static_cast<uint64>(ParseHex16(str + 24)) << 32)
|
||||||
| (static_cast<uint64>(ParseHex32(str + 28)) << 0)
|
| (static_cast<uint64>(ParseHex32(str + 28)) << 0)
|
||||||
)
|
)
|
||||||
: throw std::domain_error("");
|
: mpt::constexpr_throw<mpt::UUID>(std::domain_error(""));
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
MPT_CONSTEXPR11_FUN UUID() noexcept : Data1(0), Data2(0), Data3(0), Data4(0) { }
|
MPT_CONSTEXPR11_FUN UUID() noexcept : Data1(0), Data2(0), Data3(0), Data4(0) { }
|
||||||
|
|
|
@ -247,11 +247,12 @@ ExecResult Context::ExecutePosixShellScript(std::string script, FlagSet<ExecFlag
|
||||||
{
|
{
|
||||||
throw mpt::Wine::Exception("Creating temporary directoy failed.");
|
throw mpt::Wine::Exception("Creating temporary directoy failed.");
|
||||||
}
|
}
|
||||||
std::string dirPosix = PathToPosix(dirWindowsTemp.GetDirname());
|
const std::string dirPosix = PathToPosix(dirWindowsTemp.GetDirname());
|
||||||
if(dirPosix.empty())
|
if(dirPosix.empty())
|
||||||
{
|
{
|
||||||
throw mpt::Wine::Exception("mpt::Wine::ConvertWindowsPathToHost returned empty path.");
|
throw mpt::Wine::Exception("mpt::Wine::ConvertWindowsPathToHost returned empty path.");
|
||||||
}
|
}
|
||||||
|
const std::string dirPosixEscape = EscapePosixShell(dirPosix);
|
||||||
const mpt::PathString dirWindows = dirWindowsTemp.GetDirname();
|
const mpt::PathString dirWindows = dirWindowsTemp.GetDirname();
|
||||||
|
|
||||||
progress(userdata);
|
progress(userdata);
|
||||||
|
@ -267,11 +268,12 @@ ExecResult Context::ExecutePosixShellScript(std::string script, FlagSet<ExecFlag
|
||||||
throw mpt::Wine::Exception("Error writing script.sh.");
|
throw mpt::Wine::Exception("Error writing script.sh.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::string scriptFilenamePosix = PathToPosix(scriptFilenameWindows);
|
const std::string scriptFilenamePosix = PathToPosix(scriptFilenameWindows);
|
||||||
if(scriptFilenamePosix.empty())
|
if(scriptFilenamePosix.empty())
|
||||||
{
|
{
|
||||||
throw mpt::Wine::Exception("Error converting script.sh path.");
|
throw mpt::Wine::Exception("Error converting script.sh path.");
|
||||||
}
|
}
|
||||||
|
const std::string scriptFilenamePosixEscape = EscapePosixShell(scriptFilenamePosix);
|
||||||
|
|
||||||
progress(userdata);
|
progress(userdata);
|
||||||
|
|
||||||
|
@ -280,8 +282,8 @@ ExecResult Context::ExecutePosixShellScript(std::string script, FlagSet<ExecFlag
|
||||||
{
|
{
|
||||||
mpt::ofstream tempfile(wrapperstarterFilenameWindows, std::ios::binary);
|
mpt::ofstream tempfile(wrapperstarterFilenameWindows, std::ios::binary);
|
||||||
std::string wrapperstarterscript;
|
std::string wrapperstarterscript;
|
||||||
wrapperstarterscript += std::string() + "#!/usr/bin/env sh" + "\n";
|
wrapperstarterscript += std::string() + "#!/usr/bin/env sh" "\n";
|
||||||
wrapperstarterscript += std::string() + "exec /usr/bin/env sh " + EscapePosixShell(dirPosix) + "wrapper.sh" + "\n";
|
wrapperstarterscript += std::string() + "exec /usr/bin/env sh " + dirPosixEscape + "wrapper.sh" "\n";
|
||||||
tempfile << wrapperstarterscript;
|
tempfile << wrapperstarterscript;
|
||||||
tempfile.flush();
|
tempfile.flush();
|
||||||
if(!tempfile)
|
if(!tempfile)
|
||||||
|
@ -296,41 +298,41 @@ ExecResult Context::ExecutePosixShellScript(std::string script, FlagSet<ExecFlag
|
||||||
std::string wrapperscript;
|
std::string wrapperscript;
|
||||||
if(!flags[ExecFlagSilent])
|
if(!flags[ExecFlagSilent])
|
||||||
{
|
{
|
||||||
wrapperscript += std::string() + "printf \"\\033]0;" + title + "\\a\"" + "\n";
|
wrapperscript += "printf \"\\033]0;" + title + "\\a\"" "\n";
|
||||||
}
|
}
|
||||||
wrapperscript += std::string() + "chmod u+x " + EscapePosixShell(scriptFilenamePosix) + "\n";
|
wrapperscript += "chmod u+x " + scriptFilenamePosixEscape + "\n";
|
||||||
wrapperscript += std::string() + "cd " + EscapePosixShell(dirPosix) + "filetree" + "\n";
|
wrapperscript += "cd " + dirPosixEscape + "filetree" "\n";
|
||||||
if(flags[ExecFlagInteractive])
|
if(flags[ExecFlagInteractive])
|
||||||
{ // no stdout/stderr capturing for interactive scripts
|
{ // no stdout/stderr capturing for interactive scripts
|
||||||
wrapperscript += std::string() + EscapePosixShell(scriptFilenamePosix) + "\n";
|
wrapperscript += scriptFilenamePosixEscape + "\n";
|
||||||
wrapperscript += std::string() + "MPT_RESULT=$?" + "\n";
|
wrapperscript += "MPT_RESULT=$?" "\n";
|
||||||
wrapperscript += std::string() + "echo ${MPT_RESULT} > " + EscapePosixShell(dirPosix) + "exit" + "\n";
|
wrapperscript += "echo ${MPT_RESULT} > " + dirPosixEscape + "exit" "\n";
|
||||||
} else if(flags[ExecFlagSplitOutput])
|
} else if(flags[ExecFlagSplitOutput])
|
||||||
{
|
{
|
||||||
wrapperscript += std::string() + "(" + EscapePosixShell(scriptFilenamePosix) + "; echo $? >&4) 4>" + EscapePosixShell(dirPosix) + "exit 1>" + EscapePosixShell(dirPosix) + "out 2>" + EscapePosixShell(dirPosix) + "err" + "\n";
|
wrapperscript += "(" + scriptFilenamePosixEscape + "; echo $? >&4) 4>" + dirPosixEscape + "exit 1>" + dirPosixEscape + "out 2>" + dirPosixEscape + "err" "\n";
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
wrapperscript += std::string() + "(" + EscapePosixShell(scriptFilenamePosix) + "; echo $? >&4) 2>&1 4>" + EscapePosixShell(dirPosix) + "exit | tee " + EscapePosixShell(dirPosix) + "out" + "\n";
|
wrapperscript += "(" + scriptFilenamePosixEscape + "; echo $? >&4) 2>&1 4>" + dirPosixEscape + "exit | tee " + dirPosixEscape + "out" "\n";
|
||||||
}
|
}
|
||||||
wrapperscript += std::string() + "echo done > " + EscapePosixShell(dirPosix) + "done" + "\n";
|
wrapperscript += "echo done > " + dirPosixEscape + "done" "\n";
|
||||||
cleanupscript += std::string() + "rm " + EscapePosixShell(dirPosix) + "done" + "\n";
|
cleanupscript += "rm " + dirPosixEscape + "done" "\n";
|
||||||
cleanupscript += std::string() + "rm " + EscapePosixShell(dirPosix) + "exit" + "\n";
|
cleanupscript += "rm " + dirPosixEscape + "exit" "\n";
|
||||||
if(flags[ExecFlagInteractive])
|
if(flags[ExecFlagInteractive])
|
||||||
{
|
{
|
||||||
// nothing
|
// nothing
|
||||||
} else if(flags[ExecFlagSplitOutput])
|
} else if(flags[ExecFlagSplitOutput])
|
||||||
{
|
{
|
||||||
cleanupscript += std::string() + "rm " + EscapePosixShell(dirPosix) + "out" + "\n";
|
cleanupscript += "rm " + dirPosixEscape + "out" "\n";
|
||||||
cleanupscript += std::string() + "rm " + EscapePosixShell(dirPosix) + "err" + "\n";
|
cleanupscript += "rm " + dirPosixEscape + "err" "\n";
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
cleanupscript += std::string() + "rm " + EscapePosixShell(dirPosix) + "out" + "\n";
|
cleanupscript += "rm " + dirPosixEscape + "out" "\n";
|
||||||
}
|
}
|
||||||
cleanupscript += std::string() + "rm -r " + EscapePosixShell(dirPosix) + "filetree" + "\n";
|
cleanupscript += "rm -r " + dirPosixEscape + "filetree" "\n";
|
||||||
cleanupscript += std::string() + "rm " + EscapePosixShell(dirPosix) + "script.sh" + "\n";
|
cleanupscript += "rm " + dirPosixEscape + "script.sh" "\n";
|
||||||
cleanupscript += std::string() + "rm " + EscapePosixShell(dirPosix) + "wrapper.sh" + "\n";
|
cleanupscript += "rm " + dirPosixEscape + "wrapper.sh" "\n";
|
||||||
cleanupscript += std::string() + "rm " + EscapePosixShell(dirPosix) + "wrapperstarter.sh" + "\n";
|
cleanupscript += "rm " + dirPosixEscape + "wrapperstarter.sh" "\n";
|
||||||
cleanupscript += std::string() + "rm " + EscapePosixShell(dirPosix) + "terminal.sh" + "\n";
|
cleanupscript += "rm " + dirPosixEscape + "terminal.sh" "\n";
|
||||||
if(flags[ExecFlagAsync])
|
if(flags[ExecFlagAsync])
|
||||||
{
|
{
|
||||||
wrapperscript += cleanupscript;
|
wrapperscript += cleanupscript;
|
||||||
|
@ -346,10 +348,10 @@ ExecResult Context::ExecutePosixShellScript(std::string script, FlagSet<ExecFlag
|
||||||
|
|
||||||
progress(userdata);
|
progress(userdata);
|
||||||
|
|
||||||
::CreateDirectory((dirWindows + P_("filetree")).AsNative().c_str(), NULL);
|
::CreateDirectory((dirWindows + P_("filetree")).AsNative().c_str(), nullptr);
|
||||||
for(const auto &file : filetree)
|
for(const auto &file : filetree)
|
||||||
{
|
{
|
||||||
std::vector<mpt::ustring> path = mpt::String::Split<mpt::ustring>(mpt::ToUnicode(mpt::CharsetUTF8, file.first), U_("/"));
|
std::vector<mpt::ustring> path = mpt::String::Split<mpt::ustring>(mpt::ToUnicode(mpt::Charset::UTF8, file.first), U_("/"));
|
||||||
mpt::PathString combinedPath = dirWindows + P_("filetree") + P_("\\");
|
mpt::PathString combinedPath = dirWindows + P_("filetree") + P_("\\");
|
||||||
if(path.size() > 1)
|
if(path.size() > 1)
|
||||||
{
|
{
|
||||||
|
@ -362,7 +364,7 @@ ExecResult Context::ExecutePosixShellScript(std::string script, FlagSet<ExecFlag
|
||||||
combinedPath += mpt::PathString::FromUnicode(path[singlepath]);
|
combinedPath += mpt::PathString::FromUnicode(path[singlepath]);
|
||||||
if(!combinedPath.IsDirectory())
|
if(!combinedPath.IsDirectory())
|
||||||
{
|
{
|
||||||
if(::CreateDirectory(combinedPath.AsNative().c_str(), NULL) == 0)
|
if(::CreateDirectory(combinedPath.AsNative().c_str(), nullptr) == 0)
|
||||||
{
|
{
|
||||||
throw mpt::Wine::Exception("Error writing filetree.");
|
throw mpt::Wine::Exception("Error writing filetree.");
|
||||||
}
|
}
|
||||||
|
@ -406,8 +408,8 @@ ExecResult Context::ExecutePosixShellScript(std::string script, FlagSet<ExecFlag
|
||||||
// mate-terminal on Debian 8 cannot execute commands with arguments,
|
// mate-terminal on Debian 8 cannot execute commands with arguments,
|
||||||
// thus we use a separate script that requires no arguments to execute.
|
// thus we use a separate script that requires no arguments to execute.
|
||||||
terminalscript += "if command -v " + terminal + " 2>/dev/null 1>/dev/null ; then" "\n";
|
terminalscript += "if command -v " + terminal + " 2>/dev/null 1>/dev/null ; then" "\n";
|
||||||
terminalscript += " chmod u+x " + EscapePosixShell(dirPosix) + "wrapperstarter.sh" "\n";
|
terminalscript += " chmod u+x " + dirPosixEscape + "wrapperstarter.sh" "\n";
|
||||||
terminalscript += " exec `command -v " + terminal + "` -e \"" + EscapePosixShell(dirPosix) + "wrapperstarter.sh\"" "\n";
|
terminalscript += " exec `command -v " + terminal + "` -e \"" + dirPosixEscape + "wrapperstarter.sh\"" "\n";
|
||||||
terminalscript += "fi" "\n";
|
terminalscript += "fi" "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -430,21 +432,19 @@ ExecResult Context::ExecutePosixShellScript(std::string script, FlagSet<ExecFlag
|
||||||
|
|
||||||
if(flags[ExecFlagSilent])
|
if(flags[ExecFlagSilent])
|
||||||
{
|
{
|
||||||
unixcommand = "/usr/bin/env sh \"" + EscapePosixShell(dirPosix) + "wrapper.sh\"";
|
unixcommand = "/usr/bin/env sh \"" + dirPosixEscape + "wrapper.sh\"";
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
unixcommand = "/usr/bin/env sh \"" + EscapePosixShell(dirPosix) + "terminal.sh\"";
|
unixcommand = "/usr/bin/env sh \"" + dirPosixEscape + "terminal.sh\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
progress(userdata);
|
progress(userdata);
|
||||||
|
|
||||||
std::wstring unixcommandW = mpt::ToWide(mpt::CharsetUTF8, unixcommand);
|
std::wstring unixcommandW = mpt::ToWide(mpt::Charset::UTF8, unixcommand);
|
||||||
std::vector<WCHAR> commandline = std::vector<WCHAR>(unixcommandW.data(), unixcommandW.data() + unixcommandW.length() + 1);
|
std::wstring titleW = mpt::ToWide(mpt::Charset::UTF8, title);
|
||||||
std::wstring titleW = mpt::ToWide(mpt::CharsetUTF8, title);
|
|
||||||
std::vector<WCHAR> titleWv = std::vector<WCHAR>(titleW.data(), titleW.data() + titleW.length() + 1);
|
|
||||||
STARTUPINFOW startupInfo;
|
STARTUPINFOW startupInfo;
|
||||||
MemsetZero(startupInfo);
|
MemsetZero(startupInfo);
|
||||||
startupInfo.lpTitle = &titleWv[0];
|
startupInfo.lpTitle = titleW.data();
|
||||||
startupInfo.cb = sizeof(startupInfo);
|
startupInfo.cb = sizeof(startupInfo);
|
||||||
PROCESS_INFORMATION processInformation;
|
PROCESS_INFORMATION processInformation;
|
||||||
MemsetZero(processInformation);
|
MemsetZero(processInformation);
|
||||||
|
@ -454,15 +454,15 @@ ExecResult Context::ExecutePosixShellScript(std::string script, FlagSet<ExecFlag
|
||||||
BOOL success = FALSE;
|
BOOL success = FALSE;
|
||||||
if(flags[ExecFlagSilent])
|
if(flags[ExecFlagSilent])
|
||||||
{
|
{
|
||||||
success = CreateProcessW(NULL, &commandline[0], NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &startupInfo, &processInformation);
|
success = CreateProcessW(NULL, unixcommandW.data(), NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &startupInfo, &processInformation);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
success = CreateProcessW(NULL, &commandline[0], NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &startupInfo, &processInformation);
|
success = CreateProcessW(NULL, unixcommandW.data(), NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &startupInfo, &processInformation);
|
||||||
}
|
}
|
||||||
|
|
||||||
progress(userdata);
|
progress(userdata);
|
||||||
|
|
||||||
createProcessSuccess = (success ? true : false);
|
createProcessSuccess = (success != FALSE);
|
||||||
|
|
||||||
progress(userdata);
|
progress(userdata);
|
||||||
|
|
||||||
|
@ -495,29 +495,26 @@ ExecResult Context::ExecutePosixShellScript(std::string script, FlagSet<ExecFlag
|
||||||
|
|
||||||
progress(userdata);
|
progress(userdata);
|
||||||
|
|
||||||
// Work around Wine being able to execute PIE binaries on Debian 9.
|
// Work around Wine being unable to execute PIE binaries on Debian 9.
|
||||||
// Luckily, /bin/bash is still non-PIE on Debian 9.
|
// Luckily, /bin/bash is still non-PIE on Debian 9.
|
||||||
|
|
||||||
if(!createProcessSuccess)
|
if(!createProcessSuccess)
|
||||||
{
|
{
|
||||||
|
|
||||||
if(flags[ExecFlagSilent])
|
if(flags[ExecFlagSilent])
|
||||||
{
|
{
|
||||||
unixcommand = "/bin/bash \"" + EscapePosixShell(dirPosix) + "wrapper.sh\"";
|
unixcommand = "/bin/bash \"" + dirPosixEscape + "wrapper.sh\"";
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
unixcommand = "/bin/bash \"" + EscapePosixShell(dirPosix) + "terminal.sh\"";
|
unixcommand = "/bin/bash \"" + dirPosixEscape + "terminal.sh\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
progress(userdata);
|
progress(userdata);
|
||||||
|
|
||||||
std::wstring unixcommandW = mpt::ToWide(mpt::CharsetUTF8, unixcommand);
|
std::wstring unixcommandW = mpt::ToWide(mpt::Charset::UTF8, unixcommand);
|
||||||
std::vector<WCHAR> commandline = std::vector<WCHAR>(unixcommandW.data(), unixcommandW.data() + unixcommandW.length() + 1);
|
std::wstring titleW = mpt::ToWide(mpt::Charset::UTF8, title);
|
||||||
std::wstring titleW = mpt::ToWide(mpt::CharsetUTF8, title);
|
|
||||||
std::vector<WCHAR> titleWv = std::vector<WCHAR>(titleW.data(), titleW.data() + titleW.length() + 1);
|
|
||||||
STARTUPINFOW startupInfo;
|
STARTUPINFOW startupInfo;
|
||||||
MemsetZero(startupInfo);
|
MemsetZero(startupInfo);
|
||||||
startupInfo.lpTitle = &titleWv[0];
|
startupInfo.lpTitle = titleW.data();
|
||||||
startupInfo.cb = sizeof(startupInfo);
|
startupInfo.cb = sizeof(startupInfo);
|
||||||
PROCESS_INFORMATION processInformation;
|
PROCESS_INFORMATION processInformation;
|
||||||
MemsetZero(processInformation);
|
MemsetZero(processInformation);
|
||||||
|
@ -527,21 +524,20 @@ ExecResult Context::ExecutePosixShellScript(std::string script, FlagSet<ExecFlag
|
||||||
BOOL success = FALSE;
|
BOOL success = FALSE;
|
||||||
if(flags[ExecFlagSilent])
|
if(flags[ExecFlagSilent])
|
||||||
{
|
{
|
||||||
success = CreateProcessW(NULL, &commandline[0], NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &startupInfo, &processInformation);
|
success = CreateProcessW(NULL, unixcommandW.data(), NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &startupInfo, &processInformation);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
success = CreateProcessW(NULL, &commandline[0], NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &startupInfo, &processInformation);
|
success = CreateProcessW(NULL, unixcommandW.data(), NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &startupInfo, &processInformation);
|
||||||
}
|
}
|
||||||
|
|
||||||
progress(userdata);
|
progress(userdata);
|
||||||
|
|
||||||
createProcessSuccess = (success ? true : false);
|
createProcessSuccess = (success != FALSE);
|
||||||
|
|
||||||
progress(userdata);
|
progress(userdata);
|
||||||
|
|
||||||
if(success)
|
if(success)
|
||||||
{
|
{
|
||||||
|
|
||||||
if(!flags[ExecFlagAsync])
|
if(!flags[ExecFlagAsync])
|
||||||
{
|
{
|
||||||
// note: execution is not syncronous with all Wine versions,
|
// note: execution is not syncronous with all Wine versions,
|
||||||
|
@ -561,7 +557,6 @@ ExecResult Context::ExecutePosixShellScript(std::string script, FlagSet<ExecFlag
|
||||||
|
|
||||||
CloseHandle(processInformation.hThread);
|
CloseHandle(processInformation.hThread);
|
||||||
CloseHandle(processInformation.hProcess);
|
CloseHandle(processInformation.hProcess);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -702,8 +697,8 @@ ExecResult Context::ExecutePosixShellScript(std::string script, FlagSet<ExecFlag
|
||||||
int Context::ExecutePosixShellCommand(std::string command, std::string & output, std::string & error)
|
int Context::ExecutePosixShellCommand(std::string command, std::string & output, std::string & error)
|
||||||
{
|
{
|
||||||
std::string script;
|
std::string script;
|
||||||
script += std::string() + "#!/usr/bin/env sh" + "\n";
|
script += "#!/usr/bin/env sh" "\n";
|
||||||
script += std::string() + "exec " + command + "\n";
|
script += "exec " + command + "\n";
|
||||||
mpt::Wine::ExecResult execResult = ExecutePosixShellScript
|
mpt::Wine::ExecResult execResult = ExecutePosixShellScript
|
||||||
( script
|
( script
|
||||||
, mpt::Wine::ExecFlagSilent | mpt::Wine::ExecFlagSplitOutput, std::map<std::string, std::vector<char> >()
|
, mpt::Wine::ExecFlagSilent | mpt::Wine::ExecFlagSplitOutput, std::map<std::string, std::vector<char> >()
|
||||||
|
|
|
@ -14,9 +14,9 @@
|
||||||
|
|
||||||
#include <istream>
|
#include <istream>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include "misc_util.h"
|
#include "misc_util.h"
|
||||||
#include "mptBufferIO.h"
|
|
||||||
|
|
||||||
|
|
||||||
OPENMPT_NAMESPACE_BEGIN
|
OPENMPT_NAMESPACE_BEGIN
|
||||||
|
@ -26,11 +26,13 @@ namespace srlztn
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
//#define SSB_LOGGING
|
#ifdef MPT_ALL_LOGGING
|
||||||
|
#define SSB_LOGGING
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef SSB_LOGGING
|
#ifdef SSB_LOGGING
|
||||||
#define SSB_LOG(x) Log(x)
|
#define SSB_LOG(x) MPT_LOG(LogDebug, "serialization", x)
|
||||||
#else
|
#else
|
||||||
#define SSB_LOG(x) MPT_DO { } MPT_WHILE_0
|
#define SSB_LOG(x) MPT_DO { } MPT_WHILE_0
|
||||||
#endif
|
#endif
|
||||||
|
@ -73,7 +75,7 @@ static void WriteAdaptive12String(std::ostream& oStrm, const std::string& str)
|
||||||
|
|
||||||
void WriteItemString(std::ostream& oStrm, const std::string &str)
|
void WriteItemString(std::ostream& oStrm, const std::string &str)
|
||||||
{
|
{
|
||||||
uint32 id = static_cast<uint32>(std::min<std::size_t>(str.size(), (uint32_max >> 4))) << 4;
|
uint32 id = static_cast<uint32>(std::min(str.size(), static_cast<std::size_t>((uint32_max >> 4)))) << 4;
|
||||||
id |= 12; // 12 == 1100b
|
id |= 12; // 12 == 1100b
|
||||||
Binarywrite<uint32>(oStrm, id);
|
Binarywrite<uint32>(oStrm, id);
|
||||||
id >>= 4;
|
id >>= 4;
|
||||||
|
@ -91,7 +93,7 @@ void ReadItemString(std::istream& iStrm, std::string& str, const DataSize)
|
||||||
const uint8 nSizeBytes = (id & 12) >> 2; // 12 == 1100b
|
const uint8 nSizeBytes = (id & 12) >> 2; // 12 == 1100b
|
||||||
if (nSizeBytes > 0)
|
if (nSizeBytes > 0)
|
||||||
{
|
{
|
||||||
uint8 bytes = std::min<uint8>(3, nSizeBytes);
|
uint8 bytes = std::min(uint8(3), nSizeBytes);
|
||||||
uint8 v2 = 0;
|
uint8 v2 = 0;
|
||||||
uint8 v3 = 0;
|
uint8 v3 = 0;
|
||||||
uint8 v4 = 0;
|
uint8 v4 = 0;
|
||||||
|
@ -102,7 +104,7 @@ void ReadItemString(std::istream& iStrm, std::string& str, const DataSize)
|
||||||
id |= (v2 << 8) | (v3 << 16) | (v4 << 24);
|
id |= (v2 << 8) | (v3 << 16) | (v4 << 24);
|
||||||
}
|
}
|
||||||
// Limit to 1 MB.
|
// Limit to 1 MB.
|
||||||
str.resize(std::min<std::size_t>(id >> 4, 1000000));
|
str.resize(std::min(id >> 4, uint32(1000000)));
|
||||||
for(size_t i = 0; i < str.size(); i++)
|
for(size_t i = 0; i < str.size(); i++)
|
||||||
iStrm.read(&str[i], 1);
|
iStrm.read(&str[i], 1);
|
||||||
|
|
||||||
|
@ -116,7 +118,7 @@ mpt::ustring ID::AsString() const
|
||||||
{
|
{
|
||||||
if(IsPrintable())
|
if(IsPrintable())
|
||||||
{
|
{
|
||||||
return mpt::ToUnicode(mpt::CharsetISO8859_1, m_ID);
|
return mpt::ToUnicode(mpt::Charset::ISO8859_1, m_ID);
|
||||||
}
|
}
|
||||||
if(m_ID.length() > 8)
|
if(m_ID.length() > 8)
|
||||||
{
|
{
|
||||||
|
@ -133,22 +135,22 @@ const char Ssb::s_EntryID[3] = {'2','2','8'};
|
||||||
|
|
||||||
|
|
||||||
#ifdef SSB_LOGGING
|
#ifdef SSB_LOGGING
|
||||||
static const MPT_UCHAR_TYPE tstrWriteHeader[] = UL_("Write header with ID = %1\n");
|
static const mpt::uchar tstrWriteHeader[] = UL_("Write header with ID = %1\n");
|
||||||
static const MPT_UCHAR_TYPE tstrWriteProgress[] = UL_("Wrote entry: {num, id, rpos, size} = {%1, %2, %3, %4}\n");
|
static const mpt::uchar tstrWriteProgress[] = UL_("Wrote entry: {num, id, rpos, size} = {%1, %2, %3, %4}\n");
|
||||||
static const MPT_UCHAR_TYPE tstrWritingMap[] = UL_("Writing map to rpos: %1\n");
|
static const mpt::uchar tstrWritingMap[] = UL_("Writing map to rpos: %1\n");
|
||||||
static const MPT_UCHAR_TYPE tstrMapEntryWrite[] = UL_("Writing map entry: id=%1, rpos=%2, size=%3\n");
|
static const mpt::uchar tstrMapEntryWrite[] = UL_("Writing map entry: id=%1, rpos=%2, size=%3\n");
|
||||||
static const MPT_UCHAR_TYPE strWriteNote[] = UL_("Write note: ");
|
static const mpt::uchar strWriteNote[] = UL_("Write note: ");
|
||||||
static const MPT_UCHAR_TYPE tstrEndOfStream[] = UL_("End of stream(rpos): %1\n");
|
static const mpt::uchar tstrEndOfStream[] = UL_("End of stream(rpos): %1\n");
|
||||||
|
|
||||||
static const MPT_UCHAR_TYPE tstrReadingHeader[] = UL_("Read header with expected ID = %1\n");
|
static const mpt::uchar tstrReadingHeader[] = UL_("Read header with expected ID = %1\n");
|
||||||
static const MPT_UCHAR_TYPE strNoMapInFile[] = UL_("No map in the file.\n");
|
static const mpt::uchar strNoMapInFile[] = UL_("No map in the file.\n");
|
||||||
static const MPT_UCHAR_TYPE strIdMismatch[] = UL_("ID mismatch, terminating read.\n");
|
static const mpt::uchar strIdMismatch[] = UL_("ID mismatch, terminating read.\n");
|
||||||
static const MPT_UCHAR_TYPE strIdMatch[] = UL_("ID match, continuing reading.\n");
|
static const mpt::uchar strIdMatch[] = UL_("ID match, continuing reading.\n");
|
||||||
static const MPT_UCHAR_TYPE tstrReadingMap[] = UL_("Reading map from rpos: %1\n");
|
static const mpt::uchar tstrReadingMap[] = UL_("Reading map from rpos: %1\n");
|
||||||
static const MPT_UCHAR_TYPE tstrEndOfMap[] = UL_("End of map(rpos): %1\n");
|
static const mpt::uchar tstrEndOfMap[] = UL_("End of map(rpos): %1\n");
|
||||||
static const MPT_UCHAR_TYPE tstrReadProgress[] = UL_("Read entry: {num, id, rpos, size, desc} = {%1, %2, %3, %4, %5}\n");
|
static const mpt::uchar tstrReadProgress[] = UL_("Read entry: {num, id, rpos, size, desc} = {%1, %2, %3, %4, %5}\n");
|
||||||
static const MPT_UCHAR_TYPE tstrNoEntryFound[] = UL_("No entry with id %1 found.\n");
|
static const mpt::uchar tstrNoEntryFound[] = UL_("No entry with id %1 found.\n");
|
||||||
static const MPT_UCHAR_TYPE strReadNote[] = UL_("Read note: ");
|
static const mpt::uchar strReadNote[] = UL_("Read note: ");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -246,7 +248,7 @@ void SsbWrite::WriteMapItem(const ID &id,
|
||||||
rposDataStart,
|
rposDataStart,
|
||||||
nDatasize));
|
nDatasize));
|
||||||
|
|
||||||
mpt::ostringstream mapStream;
|
std::ostringstream mapStream;
|
||||||
|
|
||||||
if(m_nIdbytes > 0)
|
if(m_nIdbytes > 0)
|
||||||
{
|
{
|
||||||
|
@ -718,7 +720,7 @@ void SsbWrite::FinishWrite()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Seek to end.
|
// Seek to end.
|
||||||
oStrm.seekp(std::max<Postype>(posMapEnd, posDataEnd));
|
oStrm.seekp(std::max(posMapEnd, posDataEnd));
|
||||||
|
|
||||||
SSB_LOG(mpt::format(mpt::ustring(tstrEndOfStream))(oStrm.tellp() - m_posStart));
|
SSB_LOG(mpt::format(mpt::ustring(tstrEndOfStream))(oStrm.tellp() - m_posStart));
|
||||||
}
|
}
|
||||||
|
|
|
@ -180,7 +180,7 @@ template <>
|
||||||
inline void Binaryread<float>(std::istream& iStrm, float& data, const Offtype bytecount)
|
inline void Binaryread<float>(std::istream& iStrm, float& data, const Offtype bytecount)
|
||||||
{
|
{
|
||||||
typedef IEEE754binary32LE T;
|
typedef IEEE754binary32LE T;
|
||||||
mpt::byte bytes[sizeof(T)];
|
std::byte bytes[sizeof(T)];
|
||||||
std::memset(bytes, 0, sizeof(T));
|
std::memset(bytes, 0, sizeof(T));
|
||||||
mpt::IO::ReadRaw(iStrm, bytes, std::min(static_cast<std::size_t>(bytecount), sizeof(T)));
|
mpt::IO::ReadRaw(iStrm, bytes, std::min(static_cast<std::size_t>(bytecount), sizeof(T)));
|
||||||
// There is not much we can sanely do for truncated floats,
|
// There is not much we can sanely do for truncated floats,
|
||||||
|
@ -192,7 +192,7 @@ template <>
|
||||||
inline void Binaryread<double>(std::istream& iStrm, double& data, const Offtype bytecount)
|
inline void Binaryread<double>(std::istream& iStrm, double& data, const Offtype bytecount)
|
||||||
{
|
{
|
||||||
typedef IEEE754binary64LE T;
|
typedef IEEE754binary64LE T;
|
||||||
mpt::byte bytes[sizeof(T)];
|
std::byte bytes[sizeof(T)];
|
||||||
std::memset(bytes, 0, sizeof(T));
|
std::memset(bytes, 0, sizeof(T));
|
||||||
mpt::IO::ReadRaw(iStrm, bytes, std::min(static_cast<std::size_t>(bytecount), sizeof(T)));
|
mpt::IO::ReadRaw(iStrm, bytes, std::min(static_cast<std::size_t>(bytecount), sizeof(T)));
|
||||||
// There is not much we can sanely do for truncated floats,
|
// There is not much we can sanely do for truncated floats,
|
||||||
|
@ -234,7 +234,7 @@ public:
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static ID FromInt(const T &val)
|
static ID FromInt(const T &val)
|
||||||
{
|
{
|
||||||
STATIC_ASSERT(std::numeric_limits<T>::is_integer);
|
static_assert(std::numeric_limits<T>::is_integer);
|
||||||
typename mpt::make_le<T>::type valle;
|
typename mpt::make_le<T>::type valle;
|
||||||
valle = val;
|
valle = val;
|
||||||
return ID(std::string(mpt::byte_cast<const char*>(mpt::as_raw_memory(valle).data()), mpt::byte_cast<const char*>(mpt::as_raw_memory(valle).data() + sizeof(valle))));
|
return ID(std::string(mpt::byte_cast<const char*>(mpt::as_raw_memory(valle).data()), mpt::byte_cast<const char*>(mpt::as_raw_memory(valle).data() + sizeof(valle))));
|
||||||
|
|
|
@ -18,9 +18,7 @@
|
||||||
|
|
||||||
#if defined(MODPLUG_TRACKER)
|
#if defined(MODPLUG_TRACKER)
|
||||||
|
|
||||||
#if MPT_OS_WINDOWS
|
#if defined(MPT_WITH_MFC)
|
||||||
|
|
||||||
#if !defined(MPT_BUILD_WINESUPPORT)
|
|
||||||
|
|
||||||
// cppcheck-suppress missingInclude
|
// cppcheck-suppress missingInclude
|
||||||
#include <afx.h> // MFC core
|
#include <afx.h> // MFC core
|
||||||
|
@ -41,7 +39,9 @@
|
||||||
// cppcheck-suppress missingInclude
|
// cppcheck-suppress missingInclude
|
||||||
#include <afxole.h>
|
#include <afxole.h>
|
||||||
|
|
||||||
#endif // !MPT_BUILD_WINESUPPORT
|
#endif // MPT_WITH_MFC
|
||||||
|
|
||||||
|
#if MPT_OS_WINDOWS
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <windowsx.h>
|
#include <windowsx.h>
|
||||||
|
@ -61,7 +61,9 @@
|
||||||
// this will be available everywhere
|
// this will be available everywhere
|
||||||
|
|
||||||
#include "../common/mptBaseMacros.h"
|
#include "../common/mptBaseMacros.h"
|
||||||
|
// <array>
|
||||||
// <iterator>
|
// <iterator>
|
||||||
|
// <type_traits>
|
||||||
// <cstddef>
|
// <cstddef>
|
||||||
// <cstdint>
|
// <cstdint>
|
||||||
|
|
||||||
|
@ -97,23 +99,34 @@
|
||||||
// "mptBaseTypes.h"
|
// "mptBaseTypes.h"
|
||||||
// "mptSpan.h"
|
// "mptSpan.h"
|
||||||
// <utility>
|
// <utility>
|
||||||
|
// <type_traits>
|
||||||
// <cstring>
|
// <cstring>
|
||||||
|
|
||||||
#include "../common/mptAlloc.h"
|
#include "../common/mptAlloc.h"
|
||||||
// "mptBaseMacros.h"
|
// "mptBaseMacros.h"
|
||||||
// "mptMemory.h"
|
// "mptMemory.h"
|
||||||
// "mptSpan.h"
|
// "mptSpan.h"
|
||||||
|
// <array>
|
||||||
// <memory>
|
// <memory>
|
||||||
// <utility>
|
// <new>
|
||||||
// <vector>
|
// <vector>
|
||||||
|
|
||||||
#include "../common/mptString.h"
|
#include "../common/mptString.h"
|
||||||
// <algorithm>
|
// <algorithm>
|
||||||
// <limits>
|
// <limits>
|
||||||
// <string>
|
// <string>
|
||||||
|
// <string_view>
|
||||||
// <type_traits>
|
// <type_traits>
|
||||||
// <cstring>
|
// <cstring>
|
||||||
|
|
||||||
|
#include "../common/mptStringBuffer.h"
|
||||||
|
|
||||||
|
#include "../common/mptOSError.h"
|
||||||
|
// "mptException.h"
|
||||||
|
// "mptString.h"
|
||||||
|
// <exception>
|
||||||
|
// <stdexcept>
|
||||||
|
|
||||||
#include "../common/mptExceptionText.h"
|
#include "../common/mptExceptionText.h"
|
||||||
// "mptException.h"
|
// "mptException.h"
|
||||||
// "mptString.h"
|
// "mptString.h"
|
||||||
|
@ -124,6 +137,7 @@
|
||||||
#include "../common/mptPathString.h"
|
#include "../common/mptPathString.h"
|
||||||
|
|
||||||
#include "../common/Logging.h"
|
#include "../common/Logging.h"
|
||||||
|
// <atomic>
|
||||||
|
|
||||||
#include "../common/misc_util.h"
|
#include "../common/misc_util.h"
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,13 @@ OPENMPT_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define MPT_MAKE_VERSION_NUMERIC_HELPER(prefix,v0,v1,v2,v3) Version( prefix ## v0 , prefix ## v1 , prefix ## v2 , prefix ## v3 )
|
||||||
|
#define MPT_MAKE_VERSION_NUMERIC(v0,v1,v2,v3) MPT_MAKE_VERSION_NUMERIC_HELPER(0x, v0, v1, v2, v3)
|
||||||
|
|
||||||
|
#define MPT_VERSION_CURRENT MPT_MAKE_VERSION_NUMERIC(VER_MAJORMAJOR,VER_MAJOR,VER_MINOR,VER_MINORMINOR)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static_assert((MPT_VERSION_CURRENT.GetRawVersion() & 0xffffu) != 0x0000u, "Version numbers ending in .00.00 shall never exist again, as they make interpreting the version number ambiguous for file formats which can only store the two major parts of the version number (e.g. IT and S3M).");
|
static_assert((MPT_VERSION_CURRENT.GetRawVersion() & 0xffffu) != 0x0000u, "Version numbers ending in .00.00 shall never exist again, as they make interpreting the version number ambiguous for file formats which can only store the two major parts of the version number (e.g. IT and S3M).");
|
||||||
|
|
||||||
|
|
||||||
|
@ -80,10 +87,10 @@ bool Version::IsTestVersion() const noexcept
|
||||||
{
|
{
|
||||||
return (
|
return (
|
||||||
// Legacy
|
// Legacy
|
||||||
(*this > MAKE_VERSION_NUMERIC(1,17,02,54) && *this < MAKE_VERSION_NUMERIC(1,18,02,00) && *this != MAKE_VERSION_NUMERIC(1,18,00,00))
|
(*this > MPT_V("1.17.02.54") && *this < MPT_V("1.18.02.00") && *this != MPT_V("1.18.00.00"))
|
||||||
||
|
||
|
||||||
// Test builds have non-zero VER_MINORMINOR
|
// Test builds have non-zero VER_MINORMINOR
|
||||||
(*this > MAKE_VERSION_NUMERIC(1,18,02,00) && ((m_Version & 0xFFFFFF00u) != m_Version))
|
(*this > MPT_V("1.18.02.00") && ((m_Version & 0xFFFFFF00u) != m_Version))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,7 +101,7 @@ namespace Source {
|
||||||
static mpt::ustring GetUrl()
|
static mpt::ustring GetUrl()
|
||||||
{
|
{
|
||||||
#ifdef OPENMPT_VERSION_URL
|
#ifdef OPENMPT_VERSION_URL
|
||||||
return mpt::ToUnicode(mpt::CharsetASCII, OPENMPT_VERSION_URL);
|
return mpt::ToUnicode(mpt::Charset::ASCII, OPENMPT_VERSION_URL);
|
||||||
#else
|
#else
|
||||||
return mpt::ustring();
|
return mpt::ustring();
|
||||||
#endif
|
#endif
|
||||||
|
@ -132,15 +139,7 @@ static int GetRevision()
|
||||||
}
|
}
|
||||||
return ConvertStrTo<int>(svnversion);
|
return ConvertStrTo<int>(svnversion);
|
||||||
#else
|
#else
|
||||||
#if MPT_COMPILER_MSVC
|
MPT_WARNING_STATEMENT("SVN revision unknown. Please check your build system.");
|
||||||
#pragma message("SVN revision unknown. Please check your build system.")
|
|
||||||
#elif MPT_COMPILER_GCC || MPT_COMPILER_CLANG
|
|
||||||
#warning "SVN revision unknown. Please check your build system."
|
|
||||||
#else
|
|
||||||
// There is no portable way to display a warning.
|
|
||||||
// Try to provoke a warning with an unused variable.
|
|
||||||
int SVN_revision_unknown__Please_check_your_build_system;
|
|
||||||
#endif
|
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -209,7 +208,7 @@ static bool IsPackage()
|
||||||
static mpt::ustring GetSourceDate()
|
static mpt::ustring GetSourceDate()
|
||||||
{
|
{
|
||||||
#if defined(OPENMPT_VERSION_DATE)
|
#if defined(OPENMPT_VERSION_DATE)
|
||||||
return mpt::ToUnicode(mpt::CharsetASCII, OPENMPT_VERSION_DATE);
|
return mpt::ToUnicode(mpt::Charset::ASCII, OPENMPT_VERSION_DATE);
|
||||||
#else
|
#else
|
||||||
return mpt::ustring();
|
return mpt::ustring();
|
||||||
#endif
|
#endif
|
||||||
|
@ -286,9 +285,9 @@ mpt::ustring GetBuildDateString()
|
||||||
mpt::ustring result;
|
mpt::ustring result;
|
||||||
#ifdef MODPLUG_TRACKER
|
#ifdef MODPLUG_TRACKER
|
||||||
#if defined(OPENMPT_BUILD_DATE)
|
#if defined(OPENMPT_BUILD_DATE)
|
||||||
result = mpt::ToUnicode(mpt::CharsetASCII, OPENMPT_BUILD_DATE );
|
result = mpt::ToUnicode(mpt::Charset::ASCII, OPENMPT_BUILD_DATE );
|
||||||
#else
|
#else
|
||||||
result = mpt::ToUnicode(mpt::CharsetASCII, __DATE__ " " __TIME__ );
|
result = mpt::ToUnicode(mpt::Charset::ASCII, __DATE__ " " __TIME__ );
|
||||||
#endif
|
#endif
|
||||||
#else // !MODPLUG_TRACKER
|
#else // !MODPLUG_TRACKER
|
||||||
result = SourceInfo::Current().Date();
|
result = SourceInfo::Current().Date();
|
||||||
|
@ -317,18 +316,6 @@ mpt::ustring GetBuildFeaturesString()
|
||||||
mpt::ustring retval;
|
mpt::ustring retval;
|
||||||
#ifdef LIBOPENMPT_BUILD
|
#ifdef LIBOPENMPT_BUILD
|
||||||
retval = UL_("")
|
retval = UL_("")
|
||||||
#if defined(MPT_CHARSET_WIN32)
|
|
||||||
UL_(" +WINAPI")
|
|
||||||
#endif
|
|
||||||
#if defined(MPT_CHARSET_ICONV)
|
|
||||||
UL_(" +ICONV")
|
|
||||||
#endif
|
|
||||||
#if defined(MPT_CHARSET_CODECVTUTF8)
|
|
||||||
UL_(" +CODECVTUTF8")
|
|
||||||
#endif
|
|
||||||
#if defined(MPT_CHARSET_INTERNAL)
|
|
||||||
UL_(" +INTERNALCHARSETS")
|
|
||||||
#endif
|
|
||||||
#if defined(MPT_WITH_ZLIB)
|
#if defined(MPT_WITH_ZLIB)
|
||||||
UL_(" +ZLIB")
|
UL_(" +ZLIB")
|
||||||
#endif
|
#endif
|
||||||
|
@ -364,13 +351,13 @@ mpt::ustring GetBuildFeaturesString()
|
||||||
#else
|
#else
|
||||||
UL_(" -PLUGINS")
|
UL_(" -PLUGINS")
|
||||||
#endif
|
#endif
|
||||||
#if !defined(NO_DMO)
|
#if defined(MPT_WITH_DMO)
|
||||||
UL_(" +DMO")
|
UL_(" +DMO")
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
#endif
|
#endif
|
||||||
#ifdef MODPLUG_TRACKER
|
#ifdef MODPLUG_TRACKER
|
||||||
MPT_CONSTANT_IF(mpt::arch_bits == 64)
|
if constexpr(mpt::arch_bits == 64)
|
||||||
{
|
{
|
||||||
if (true
|
if (true
|
||||||
&& (mpt::Windows::Version::GetMinimumKernelLevel() <= mpt::Windows::Version::WinXP64)
|
&& (mpt::Windows::Version::GetMinimumKernelLevel() <= mpt::Windows::Version::WinXP64)
|
||||||
|
@ -378,7 +365,7 @@ mpt::ustring GetBuildFeaturesString()
|
||||||
) {
|
) {
|
||||||
retval += UL_(" WIN64OLD");
|
retval += UL_(" WIN64OLD");
|
||||||
}
|
}
|
||||||
} else MPT_CONSTANT_IF(mpt::arch_bits == 32)
|
} else if constexpr(mpt::arch_bits == 32)
|
||||||
{
|
{
|
||||||
if (true
|
if (true
|
||||||
&& (mpt::Windows::Version::GetMinimumKernelLevel() <= mpt::Windows::Version::WinXP)
|
&& (mpt::Windows::Version::GetMinimumKernelLevel() <= mpt::Windows::Version::WinXP)
|
||||||
|
@ -396,7 +383,7 @@ mpt::ustring GetBuildFeaturesString()
|
||||||
#ifdef NO_VST
|
#ifdef NO_VST
|
||||||
UL_(" NO_VST")
|
UL_(" NO_VST")
|
||||||
#endif
|
#endif
|
||||||
#ifdef NO_DMO
|
#ifndef MPT_WITH_DMO
|
||||||
UL_(" NO_DMO")
|
UL_(" NO_DMO")
|
||||||
#endif
|
#endif
|
||||||
#ifdef NO_PLUGINS
|
#ifdef NO_PLUGINS
|
||||||
|
@ -588,19 +575,19 @@ mpt::ustring GetURL(Build::Url key)
|
||||||
|
|
||||||
mpt::ustring GetFullCreditsString()
|
mpt::ustring GetFullCreditsString()
|
||||||
{
|
{
|
||||||
return mpt::ToUnicode(mpt::CharsetUTF8,
|
return mpt::ToUnicode(mpt::Charset::UTF8,
|
||||||
#ifdef MODPLUG_TRACKER
|
#ifdef MODPLUG_TRACKER
|
||||||
"OpenMPT / ModPlug Tracker\n"
|
"OpenMPT / ModPlug Tracker\n"
|
||||||
#else
|
#else
|
||||||
"libopenmpt (based on OpenMPT / ModPlug Tracker)\n"
|
"libopenmpt (based on OpenMPT / ModPlug Tracker)\n"
|
||||||
#endif
|
#endif
|
||||||
"\n"
|
"\n"
|
||||||
"Copyright \xC2\xA9 2004-2019 Contributors\n"
|
"Copyright \xC2\xA9 2004-2020 Contributors\n"
|
||||||
"Copyright \xC2\xA9 1997-2003 Olivier Lapicque\n"
|
"Copyright \xC2\xA9 1997-2003 Olivier Lapicque\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Contributors:\n"
|
"Contributors:\n"
|
||||||
"Johannes Schultz (2008-2019)\n"
|
"Johannes Schultz (2008-2020)\n"
|
||||||
"J\xC3\xB6rn Heusipp (2012-2019)\n"
|
"J\xC3\xB6rn Heusipp (2012-2020)\n"
|
||||||
"Ahti Lepp\xC3\xA4nen (2005-2011)\n"
|
"Ahti Lepp\xC3\xA4nen (2005-2011)\n"
|
||||||
"Robin Fernandes (2004-2007)\n"
|
"Robin Fernandes (2004-2007)\n"
|
||||||
"Sergiy Pylypenko (2007)\n"
|
"Sergiy Pylypenko (2007)\n"
|
||||||
|
@ -610,6 +597,7 @@ mpt::ustring GetFullCreditsString()
|
||||||
"\n"
|
"\n"
|
||||||
"Additional patch submitters:\n"
|
"Additional patch submitters:\n"
|
||||||
"coda (https://coda.s3m.us/)\n"
|
"coda (https://coda.s3m.us/)\n"
|
||||||
|
"Jo\xC3\xA3o Baptista de Paula e Silva (https://joaobapt.com/)\n"
|
||||||
"kode54 (https://kode54.net/)\n"
|
"kode54 (https://kode54.net/)\n"
|
||||||
"Revenant (https://revenant1.net/)\n"
|
"Revenant (https://revenant1.net/)\n"
|
||||||
"xaimus (http://xaimus.com/)\n"
|
"xaimus (http://xaimus.com/)\n"
|
||||||
|
@ -657,6 +645,9 @@ mpt::ustring GetFullCreditsString()
|
||||||
"Shayde / Reality Productions for Opal OPL3 emulator\n"
|
"Shayde / Reality Productions for Opal OPL3 emulator\n"
|
||||||
"https://www.3eality.com/\n"
|
"https://www.3eality.com/\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
"Ryuhei Mori for TinyFFT\n"
|
||||||
|
"https://github.com/ryuhei-mori/tinyfft\n"
|
||||||
|
"\n"
|
||||||
#ifdef MPT_WITH_ZLIB
|
#ifdef MPT_WITH_ZLIB
|
||||||
"Jean-loup Gailly and Mark Adler for zlib\n"
|
"Jean-loup Gailly and Mark Adler for zlib\n"
|
||||||
"https://zlib.net/\n"
|
"https://zlib.net/\n"
|
||||||
|
@ -736,7 +727,8 @@ mpt::ustring GetFullCreditsString()
|
||||||
#endif
|
#endif
|
||||||
#if defined(MPT_WITH_LAME)
|
#if defined(MPT_WITH_LAME)
|
||||||
"The LAME project for LAME\n"
|
"The LAME project for LAME\n"
|
||||||
"http://lame.sourceforge.net/\n"
|
"https://lame.sourceforge.io/\n"
|
||||||
|
"\n"
|
||||||
#endif
|
#endif
|
||||||
#if defined(MPT_WITH_NLOHMANNJSON)
|
#if defined(MPT_WITH_NLOHMANNJSON)
|
||||||
"Niels Lohmann et al. for nlohmann-json\n"
|
"Niels Lohmann et al. for nlohmann-json\n"
|
||||||
|
@ -785,7 +777,7 @@ mpt::ustring GetFullCreditsString()
|
||||||
mpt::ustring GetLicenseString()
|
mpt::ustring GetLicenseString()
|
||||||
{
|
{
|
||||||
return MPT_UTF8(
|
return MPT_UTF8(
|
||||||
"Copyright (c) 2004-2019, OpenMPT contributors" "\n"
|
"Copyright (c) 2004-2020, OpenMPT contributors" "\n"
|
||||||
"Copyright (c) 1997-2003, Olivier Lapicque" "\n"
|
"Copyright (c) 1997-2003, Olivier Lapicque" "\n"
|
||||||
"All rights reserved." "\n"
|
"All rights reserved." "\n"
|
||||||
"" "\n"
|
"" "\n"
|
||||||
|
|
|
@ -12,8 +12,11 @@
|
||||||
|
|
||||||
#include "BuildSettings.h"
|
#include "BuildSettings.h"
|
||||||
|
|
||||||
|
#include "mptString.h"
|
||||||
#include "FlagSet.h"
|
#include "FlagSet.h"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
|
||||||
OPENMPT_NAMESPACE_BEGIN
|
OPENMPT_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
@ -106,6 +109,74 @@ public:
|
||||||
// Returns true if a given version number is from a test build, false if it's a release build.
|
// Returns true if a given version number is from a test build, false if it's a release build.
|
||||||
bool IsTestVersion() const noexcept;
|
bool IsTestVersion() const noexcept;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
struct LiteralParser
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Work-around for GCC 5 which complains about instanciating non-literal type inside a constexpr function when using mpt::constexpr_throw(std::runtime_error("")).
|
||||||
|
struct ParseException {};
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
static MPT_CONSTEXPR11_FUN uint8 NibbleFromChar(char x)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
('0' <= x && x <= '9') ? static_cast<uint8>(x - '0' + 0) :
|
||||||
|
('a' <= x && x <= 'z') ? static_cast<uint8>(x - 'a' + 10) :
|
||||||
|
('A' <= x && x <= 'Z') ? static_cast<uint8>(x - 'A' + 10) :
|
||||||
|
mpt::constexpr_throw<uint8>(std::domain_error(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
static MPT_CONSTEXPR14_FUN Version Parse(const char * str, std::size_t len)
|
||||||
|
{
|
||||||
|
// 0123456789
|
||||||
|
// 1.23.45.67
|
||||||
|
uint8 v[4] = {0, 0, 0, 0};
|
||||||
|
std::size_t field = 0;
|
||||||
|
std::size_t fieldlen = 0;
|
||||||
|
for(std::size_t i = 0; i < len; ++i)
|
||||||
|
{
|
||||||
|
char c = str[i];
|
||||||
|
if(c == '.')
|
||||||
|
{
|
||||||
|
if(field >= 3)
|
||||||
|
{
|
||||||
|
mpt::constexpr_throw(ParseException());
|
||||||
|
}
|
||||||
|
if(fieldlen == 0)
|
||||||
|
{
|
||||||
|
mpt::constexpr_throw(ParseException());
|
||||||
|
}
|
||||||
|
field++;
|
||||||
|
fieldlen = 0;
|
||||||
|
} else if(('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'))
|
||||||
|
{
|
||||||
|
fieldlen++;
|
||||||
|
if(fieldlen > 2)
|
||||||
|
{
|
||||||
|
mpt::constexpr_throw(ParseException());
|
||||||
|
}
|
||||||
|
v[field] <<= 4;
|
||||||
|
v[field] |= NibbleFromChar(c);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
mpt::constexpr_throw(ParseException());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(fieldlen == 0)
|
||||||
|
{
|
||||||
|
mpt::constexpr_throw(ParseException());
|
||||||
|
}
|
||||||
|
return Version(v[0], v[1], v[2], v[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
MPT_CONSTEXPR11_FUN bool operator == (const Version &a, const Version &b) noexcept
|
MPT_CONSTEXPR11_FUN bool operator == (const Version &a, const Version &b) noexcept
|
||||||
|
@ -134,11 +205,15 @@ MPT_CONSTEXPR11_FUN bool operator > (const Version &a, const Version &b) noexcep
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//Creates version number from version parts that appears in version string.
|
MPT_CONSTEXPR14_FUN Version operator "" _LiteralVersionImpl (const char * str, std::size_t len)
|
||||||
//For example MAKE_VERSION_NUMERIC(1,17,02,28) gives version number of
|
{
|
||||||
//version 1.17.02.28.
|
return Version::LiteralParser::Parse(str, len);
|
||||||
#define MPT_MAKE_VERSION_NUMERIC_HELPER(prefix,v0,v1,v2,v3) Version( prefix ## v0 , prefix ## v1 , prefix ## v2 , prefix ## v3 )
|
}
|
||||||
#define MAKE_VERSION_NUMERIC(v0,v1,v2,v3) MPT_MAKE_VERSION_NUMERIC_HELPER(0x, v0, v1, v2, v3)
|
|
||||||
|
// Create Version object from version string and check syntax, all at compile time.
|
||||||
|
// cppcheck false-positive
|
||||||
|
// cppcheck-suppress preprocessorErrorDirective
|
||||||
|
#define MPT_V(strver) Version{MPT_FORCE_CONSTEXPR(( strver ## _LiteralVersionImpl ).GetRawVersion())}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* versionNumber.h
|
* versionNumber.h
|
||||||
* ---------------
|
* ---------------
|
||||||
* Purpose: OpenMPT version handling.
|
* Purpose: OpenMPT version number.
|
||||||
* Notes : (currently none)
|
* Notes : (currently none)
|
||||||
* Authors: OpenMPT Devs
|
* Authors: OpenMPT Devs
|
||||||
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
|
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
|
||||||
|
@ -14,16 +14,10 @@
|
||||||
|
|
||||||
OPENMPT_NAMESPACE_BEGIN
|
OPENMPT_NAMESPACE_BEGIN
|
||||||
|
|
||||||
#define VER_HELPER_STRINGIZE(x) #x
|
// Version definitions. The only thing that needs to be changed when changing version number.
|
||||||
#define VER_STRINGIZE(x) VER_HELPER_STRINGIZE(x)
|
|
||||||
|
|
||||||
//Version definitions. The only thing that needs to be changed when changing version number.
|
|
||||||
#define VER_MAJORMAJOR 1
|
#define VER_MAJORMAJOR 1
|
||||||
#define VER_MAJOR 28
|
#define VER_MAJOR 29
|
||||||
#define VER_MINOR 08
|
#define VER_MINOR 03
|
||||||
#define VER_MINORMINOR 00
|
#define VER_MINORMINOR 00
|
||||||
|
|
||||||
//Numerical value of the version.
|
|
||||||
#define MPT_VERSION_CURRENT MAKE_VERSION_NUMERIC(VER_MAJORMAJOR,VER_MAJOR,VER_MINOR,VER_MINORMINOR)
|
|
||||||
|
|
||||||
OPENMPT_NAMESPACE_END
|
OPENMPT_NAMESPACE_END
|
||||||
|
|
|
@ -7,9 +7,6 @@ mkdir $FUZZING_TEMPDIR
|
||||||
sudo mount -t tmpfs -o size=200M none $FUZZING_TEMPDIR
|
sudo mount -t tmpfs -o size=200M none $FUZZING_TEMPDIR
|
||||||
rm -rf $FUZZING_TEMPDIR/bin
|
rm -rf $FUZZING_TEMPDIR/bin
|
||||||
mkdir $FUZZING_TEMPDIR/bin
|
mkdir $FUZZING_TEMPDIR/bin
|
||||||
cp ../../bin/* $FUZZING_TEMPDIR/bin/
|
cp -d ../../bin/* $FUZZING_TEMPDIR/bin/
|
||||||
rm $FUZZING_TEMPDIR/bin/libopenmpt.so
|
|
||||||
cp ../../bin/libopenmpt.so.1 $FUZZING_TEMPDIR/bin/libopenmpt.so
|
|
||||||
cp ../../bin/libopenmpt.so.1 $FUZZING_TEMPDIR/bin/libopenmpt.so.1
|
|
||||||
|
|
||||||
LD_LIBRARY_PATH=$FUZZING_TEMPDIR/bin $AFL_BIN -f $FUZZING_TEMPDIR/infile01 -x all_formats.dict -t $FUZZING_TIMEOUT $FUZZING_INPUT -o $FUZZING_FINDINGS_DIR -M fuzzer01 $FUZZING_TEMPDIR/bin/fuzz $FUZZING_TEMPDIR/infile01
|
LD_LIBRARY_PATH=$FUZZING_TEMPDIR/bin $AFL_BIN -f $FUZZING_TEMPDIR/infile01 -x all_formats.dict -t $FUZZING_TIMEOUT $FUZZING_INPUT -o $FUZZING_FINDINGS_DIR -M fuzzer01 $FUZZING_TEMPDIR/bin/fuzz $FUZZING_TEMPDIR/infile01
|
||||||
|
|
|
@ -1,21 +1,16 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
cd "${0%/*}"
|
cd "${0%/*}"
|
||||||
|
|
||||||
AFL_VERSION="$(wget --quiet -O - "https://api.github.com/repos/google/AFL/releases/latest" | grep -Po '"tag_name": "\K.*?(?=")')"
|
AFL_VERSION="$(wget --quiet -O - "https://api.github.com/repos/vanhauser-thc/AFLplusplus/releases/latest" | grep -Po '"tag_name": "\K.*?(?=")')"
|
||||||
AFL_FILENAME="$AFL_VERSION.tar.gz"
|
AFL_FILENAME="$AFL_VERSION.tar.gz"
|
||||||
AFL_URL="https://github.com/google/AFL/archive/$AFL_FILENAME"
|
AFL_URL="https://github.com/vanhauser-thc/AFLplusplus/archive/$AFL_FILENAME"
|
||||||
|
|
||||||
rm $AFL_FILENAME
|
rm $AFL_FILENAME
|
||||||
wget $AFL_URL || exit
|
wget $AFL_URL || exit
|
||||||
tar -xzvf $AFL_FILENAME
|
tar -xzvf $AFL_FILENAME
|
||||||
rm $AFL_FILENAME
|
rm $AFL_FILENAME
|
||||||
cd AFL-*
|
cd AFLplusplus-*
|
||||||
make || exit
|
make source-only || exit
|
||||||
cd llvm_mode
|
cd ..
|
||||||
# may need to prepend LLVM_CONFIG=/usr/bin/llvm-config-3.8 or similar, depending on the system
|
|
||||||
make || exit
|
|
||||||
cd ../libdislocator
|
|
||||||
make || exit
|
|
||||||
cd ../..
|
|
||||||
rm -rf afl
|
rm -rf afl
|
||||||
mv AFL-* afl
|
mv AFLplusplus-* afl
|
|
@ -0,0 +1,26 @@
|
||||||
|
Copyright (c) 2004-2020, OpenMPT contributors
|
||||||
|
Copyright (c) 1997-2003, Olivier Lapicque
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of the OpenMPT project nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
|
||||||
|
ACLOCAL_AMFLAGS = -I m4 --install
|
||||||
|
EXTRA_DIST =
|
||||||
|
EXTRA_DIST += LICENSE
|
||||||
|
EXTRA_DIST += libopenmpt_modplug.pc.in
|
||||||
|
EXTRA_DIST += libmodplug.pc.in
|
||||||
|
EXTRA_DIST += test.sh
|
||||||
|
MOSTLYCLEANFILES =
|
||||||
|
|
||||||
|
dist_doc_DATA =
|
||||||
|
dist_doc_DATA += LICENSE
|
||||||
|
nobase_dist_doc_DATA =
|
||||||
|
|
||||||
|
bin_PROGRAMS =
|
||||||
|
check_PROGRAMS =
|
||||||
|
lib_LTLIBRARIES =
|
||||||
|
|
||||||
|
pkgconfigdir = $(libdir)/pkgconfig
|
||||||
|
pkgconfig_DATA =
|
||||||
|
nobase_include_HEADERS =
|
||||||
|
|
||||||
|
if ENABLE_LIBOPENMPT_MODPLUG
|
||||||
|
lib_LTLIBRARIES += libopenmpt_modplug.la
|
||||||
|
libopenmpt_modplug_la_LDFLAGS = -version-info 1:0:0 -no-undefined
|
||||||
|
libopenmpt_modplug_la_CPPFLAGS = -I$(srcdir)/ $(LIBOPENMPT_CPPFLAGS)
|
||||||
|
libopenmpt_modplug_la_CXXFLAGS = $(LIBOPENMPT_CFLAGS)
|
||||||
|
libopenmpt_modplug_la_CFLAGS = $(LIBOPENMPT_CFLAGS)
|
||||||
|
libopenmpt_modplug_la_LIBADD = $(LIBOPENMPT_LIBS)
|
||||||
|
libopenmpt_modplug_la_SOURCES =
|
||||||
|
libopenmpt_modplug_la_SOURCES += libopenmpt_modplug.c
|
||||||
|
libopenmpt_modplug_la_SOURCES += libopenmpt_modplug_cpp.cpp
|
||||||
|
endif
|
||||||
|
|
||||||
|
if ENABLE_LIBMODPLUG
|
||||||
|
pkgconfig_DATA += libmodplug.pc
|
||||||
|
lib_LTLIBRARIES += libmodplug.la
|
||||||
|
libmodplug_la_LDFLAGS = -version-info 1:0:0 -no-undefined
|
||||||
|
nobase_include_HEADERS += libmodplug/modplug.h libmodplug/sndfile.h libmodplug/stdafx.h
|
||||||
|
libmodplug_la_CPPFLAGS = -I$(srcdir)/ $(LIBOPENMPT_CPPFLAGS)
|
||||||
|
libmodplug_la_CXXFLAGS = $(LIBOPENMPT_CFLAGS)
|
||||||
|
libmodplug_la_CFLAGS = $(LIBOPENMPT_CFLAGS)
|
||||||
|
libmodplug_la_LIBADD = $(LIBOPENMPT_LIBS)
|
||||||
|
libmodplug_la_SOURCES =
|
||||||
|
libmodplug_la_SOURCES += libopenmpt_modplug.c
|
||||||
|
libmodplug_la_SOURCES += libopenmpt_modplug_cpp.cpp
|
||||||
|
endif
|
2
Frameworks/OpenMPT/OpenMPT/contrib/libmodplug-0.8.8.5/autogen.sh
Executable file
2
Frameworks/OpenMPT/OpenMPT/contrib/libmodplug-0.8.8.5/autogen.sh
Executable file
|
@ -0,0 +1,2 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
autoreconf -i
|
7
Frameworks/OpenMPT/OpenMPT/contrib/libmodplug-0.8.8.5/clean.sh
Executable file
7
Frameworks/OpenMPT/OpenMPT/contrib/libmodplug-0.8.8.5/clean.sh
Executable file
|
@ -0,0 +1,7 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
./autogen.sh
|
||||||
|
./configure
|
||||||
|
make distclean
|
|
@ -0,0 +1,81 @@
|
||||||
|
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||||
|
|
||||||
|
/* define if the compiler supports basic C++11 syntax */
|
||||||
|
#undef HAVE_CXX11
|
||||||
|
|
||||||
|
/* define if the compiler supports basic C++14 syntax */
|
||||||
|
#undef HAVE_CXX14
|
||||||
|
|
||||||
|
/* define if the compiler supports basic C++17 syntax */
|
||||||
|
#undef HAVE_CXX17
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||||
|
#undef HAVE_DLFCN_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||||
|
#undef HAVE_INTTYPES_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <memory.h> header file. */
|
||||||
|
#undef HAVE_MEMORY_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdint.h> header file. */
|
||||||
|
#undef HAVE_STDINT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||||
|
#undef HAVE_STDLIB_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <strings.h> header file. */
|
||||||
|
#undef HAVE_STRINGS_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <string.h> header file. */
|
||||||
|
#undef HAVE_STRING_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||||
|
#undef HAVE_SYS_STAT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||||
|
#undef HAVE_SYS_TYPES_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <unistd.h> header file. */
|
||||||
|
#undef HAVE_UNISTD_H
|
||||||
|
|
||||||
|
/* Define to the sub-directory where libtool stores uninstalled libraries. */
|
||||||
|
#undef LT_OBJDIR
|
||||||
|
|
||||||
|
/* Name of package */
|
||||||
|
#undef PACKAGE
|
||||||
|
|
||||||
|
/* Define to the address where bug reports for this package should be sent. */
|
||||||
|
#undef PACKAGE_BUGREPORT
|
||||||
|
|
||||||
|
/* Define to the full name of this package. */
|
||||||
|
#undef PACKAGE_NAME
|
||||||
|
|
||||||
|
/* Define to the full name and version of this package. */
|
||||||
|
#undef PACKAGE_STRING
|
||||||
|
|
||||||
|
/* Define to the one symbol short name of this package. */
|
||||||
|
#undef PACKAGE_TARNAME
|
||||||
|
|
||||||
|
/* Define to the home page for this package. */
|
||||||
|
#undef PACKAGE_URL
|
||||||
|
|
||||||
|
/* Define to the version of this package. */
|
||||||
|
#undef PACKAGE_VERSION
|
||||||
|
|
||||||
|
/* Define to 1 if you have the ANSI C header files. */
|
||||||
|
#undef STDC_HEADERS
|
||||||
|
|
||||||
|
/* Version number of package */
|
||||||
|
#undef VERSION
|
||||||
|
|
||||||
|
/* Enable large inode numbers on Mac OS X 10.5. */
|
||||||
|
#ifndef _DARWIN_USE_64_BIT_INODE
|
||||||
|
# define _DARWIN_USE_64_BIT_INODE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||||
|
#undef _FILE_OFFSET_BITS
|
||||||
|
|
||||||
|
/* Define for large files, on AIX-style hosts. */
|
||||||
|
#undef _LARGE_FILES
|
|
@ -0,0 +1,66 @@
|
||||||
|
AC_INIT([libopenmpt-modplug], [0.8.8.5-openmpt1], [https://bugs.openmpt.org/], [libopenmpt-modplug], [https://lib.openmpt.org/])
|
||||||
|
AC_PREREQ([2.68])
|
||||||
|
|
||||||
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
|
AC_CONFIG_HEADERS([config.h])
|
||||||
|
AC_CONFIG_AUX_DIR([build-aux])
|
||||||
|
AC_CONFIG_FILES([Makefile libopenmpt_modplug.pc libmodplug.pc])
|
||||||
|
|
||||||
|
AM_INIT_AUTOMAKE([1.11 -Wall -Werror foreign subdir-objects])
|
||||||
|
|
||||||
|
AM_PROG_AR
|
||||||
|
|
||||||
|
LT_INIT
|
||||||
|
|
||||||
|
AC_SYS_LARGEFILE
|
||||||
|
|
||||||
|
PKG_PROG_PKG_CONFIG([0.24])
|
||||||
|
AC_PROG_CC
|
||||||
|
AM_PROG_CC_C_O
|
||||||
|
AC_PROG_CXX
|
||||||
|
AC_PROG_INSTALL
|
||||||
|
|
||||||
|
LIBOPENMPT_REQUIRES_PRIVATE=
|
||||||
|
LIBOPENMPT_LIBS_PRIVATE=
|
||||||
|
|
||||||
|
# We want a modern C compiler
|
||||||
|
AC_PROG_CC_STDC
|
||||||
|
#AC_PROG_CC_C99
|
||||||
|
|
||||||
|
# We need C++11 support
|
||||||
|
AX_CXX_COMPILE_STDCXX(17, [noext], [optional])
|
||||||
|
AS_IF([test "x$HAVE_CXX17" != "x1"],
|
||||||
|
[
|
||||||
|
AX_CXX_COMPILE_STDCXX(14, [noext], [optional])
|
||||||
|
AS_IF([test "x$HAVE_CXX14" != "x1"],
|
||||||
|
[
|
||||||
|
AX_CXX_COMPILE_STDCXX(11, [noext], [mandatory])
|
||||||
|
],[]
|
||||||
|
)
|
||||||
|
],[]
|
||||||
|
)
|
||||||
|
|
||||||
|
AC_LANG_PUSH([C])
|
||||||
|
AX_CHECK_COMPILE_FLAG([-fvisibility=hidden], [CFLAGS="$CFLAGS -fvisibility=hidden"])
|
||||||
|
AX_CFLAGS_WARN_ALL
|
||||||
|
AC_LANG_POP([C])
|
||||||
|
|
||||||
|
AC_LANG_PUSH([C++])
|
||||||
|
AX_CHECK_COMPILE_FLAG([-fvisibility=hidden], [CXXFLAGS="$CXXFLAGS -fvisibility=hidden"])
|
||||||
|
AX_CXXFLAGS_WARN_ALL
|
||||||
|
AC_LANG_POP([C++])
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES([LIBOPENMPT], [libopenmpt])
|
||||||
|
|
||||||
|
# libmodplug emulation
|
||||||
|
AC_ARG_ENABLE([libopenmpt_modplug], AS_HELP_STRING([--disable-libopenmpt_modplug], [Disable the libopenmpt_modplug emulation library of the libmodplug interface.]))
|
||||||
|
AM_CONDITIONAL([ENABLE_LIBOPENMPT_MODPLUG], [test "x$enable_libopenmpt_modplug" != "xno"])
|
||||||
|
|
||||||
|
# libmodplug replacement
|
||||||
|
AC_ARG_ENABLE([libmodplug], AS_HELP_STRING([--enable-libmodplug], [Enable libmodplug replacement library based on libopenmpt.
|
||||||
|
WARNING: This will replace your current libmodplug installation.
|
||||||
|
CAUTION: The emulation of the libmodplug interface is not complete as libmodplug exposes lots of internal implementation details. If any of those is used by an application, the emulation via libopenmpt will fail and/or crash.
|
||||||
|
]))
|
||||||
|
AM_CONDITIONAL([ENABLE_LIBMODPLUG], [test "x$enable_libmodplug" = "xyes"])
|
||||||
|
|
||||||
|
AC_OUTPUT
|
9
Frameworks/OpenMPT/OpenMPT/contrib/libmodplug-0.8.8.5/dist.sh
Executable file
9
Frameworks/OpenMPT/OpenMPT/contrib/libmodplug-0.8.8.5/dist.sh
Executable file
|
@ -0,0 +1,9 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
./test.sh
|
||||||
|
|
||||||
|
./autogen.sh
|
||||||
|
./configure
|
||||||
|
make dist
|
|
@ -5,7 +5,7 @@ includedir=${prefix}/include
|
||||||
|
|
||||||
Name: libmodplug
|
Name: libmodplug
|
||||||
Description: The ModPlug mod file playing library (emulated via libopenmpt).
|
Description: The ModPlug mod file playing library (emulated via libopenmpt).
|
||||||
Version: 0.8.8.5
|
Version: @PACKAGE_VERSION@
|
||||||
Requires.private: libopenmpt
|
Requires.private: libopenmpt
|
||||||
Libs: -L${libdir} -lmodplug
|
Libs: -L${libdir} -lmodplug
|
||||||
Libs.private:
|
Libs.private:
|
|
@ -19,7 +19,7 @@
|
||||||
#endif
|
#endif
|
||||||
#endif /* _MSC_VER */
|
#endif /* _MSC_VER */
|
||||||
|
|
||||||
#include "libopenmpt.h"
|
#include <libopenmpt/libopenmpt.h>
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
|
@ -0,0 +1,12 @@
|
||||||
|
prefix=@prefix@
|
||||||
|
exec_prefix=@exec_prefix@
|
||||||
|
libdir=@libdir@
|
||||||
|
includedir=${prefix}/include
|
||||||
|
|
||||||
|
Name: libopenmpt_modplug
|
||||||
|
Description: The ModPlug mod file playing library (emulated via libopenmpt).
|
||||||
|
Version: @PACKAGE_VERSION@
|
||||||
|
Requires.private: libopenmpt
|
||||||
|
Libs: -L${libdir} -lopenmpt_modplug
|
||||||
|
Libs.private:
|
||||||
|
Cflags: -I${includedir}
|
|
@ -36,7 +36,7 @@ Metadata and other state is not provided or updated.
|
||||||
#endif
|
#endif
|
||||||
#endif /* _MSC_VER */
|
#endif /* _MSC_VER */
|
||||||
|
|
||||||
#include "libopenmpt.hpp"
|
#include <libopenmpt/libopenmpt.hpp>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
|
@ -0,0 +1,972 @@
|
||||||
|
# ===========================================================================
|
||||||
|
# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html
|
||||||
|
# ===========================================================================
|
||||||
|
#
|
||||||
|
# SYNOPSIS
|
||||||
|
#
|
||||||
|
# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional])
|
||||||
|
#
|
||||||
|
# DESCRIPTION
|
||||||
|
#
|
||||||
|
# Check for baseline language coverage in the compiler for the specified
|
||||||
|
# version of the C++ standard. If necessary, add switches to CXX and
|
||||||
|
# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard)
|
||||||
|
# or '14' (for the C++14 standard).
|
||||||
|
#
|
||||||
|
# The second argument, if specified, indicates whether you insist on an
|
||||||
|
# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
|
||||||
|
# -std=c++11). If neither is specified, you get whatever works, with
|
||||||
|
# preference for an extended mode.
|
||||||
|
#
|
||||||
|
# The third argument, if specified 'mandatory' or if left unspecified,
|
||||||
|
# indicates that baseline support for the specified C++ standard is
|
||||||
|
# required and that the macro should error out if no mode with that
|
||||||
|
# support is found. If specified 'optional', then configuration proceeds
|
||||||
|
# regardless, after defining HAVE_CXX${VERSION} if and only if a
|
||||||
|
# supporting mode is found.
|
||||||
|
#
|
||||||
|
# LICENSE
|
||||||
|
#
|
||||||
|
# Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com>
|
||||||
|
# Copyright (c) 2012 Zack Weinberg <zackw@panix.com>
|
||||||
|
# Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu>
|
||||||
|
# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov@google.com>
|
||||||
|
# Copyright (c) 2015 Paul Norman <penorman@mac.com>
|
||||||
|
# Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>
|
||||||
|
# Copyright (c) 2016, 2018 Krzesimir Nowak <qdlacz@gmail.com>
|
||||||
|
#
|
||||||
|
# Copying and distribution of this file, with or without modification, are
|
||||||
|
# permitted in any medium without royalty provided the copyright notice
|
||||||
|
# and this notice are preserved. This file is offered as-is, without any
|
||||||
|
# warranty.
|
||||||
|
|
||||||
|
#serial 9
|
||||||
|
|
||||||
|
dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
|
||||||
|
dnl (serial version number 13).
|
||||||
|
|
||||||
|
AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
|
||||||
|
m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"],
|
||||||
|
[$1], [14], [ax_cxx_compile_alternatives="14 1y"],
|
||||||
|
[$1], [17], [ax_cxx_compile_alternatives="17 1z"],
|
||||||
|
[m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl
|
||||||
|
m4_if([$2], [], [],
|
||||||
|
[$2], [ext], [],
|
||||||
|
[$2], [noext], [],
|
||||||
|
[m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl
|
||||||
|
m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true],
|
||||||
|
[$3], [mandatory], [ax_cxx_compile_cxx$1_required=true],
|
||||||
|
[$3], [optional], [ax_cxx_compile_cxx$1_required=false],
|
||||||
|
[m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])])
|
||||||
|
AC_LANG_PUSH([C++])dnl
|
||||||
|
ac_success=no
|
||||||
|
|
||||||
|
m4_if([$2], [noext], [], [dnl
|
||||||
|
if test x$ac_success = xno; then
|
||||||
|
for alternative in ${ax_cxx_compile_alternatives}; do
|
||||||
|
switch="-std=gnu++${alternative}"
|
||||||
|
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
|
||||||
|
AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
|
||||||
|
$cachevar,
|
||||||
|
[ac_save_CXX="$CXX"
|
||||||
|
CXX="$CXX $switch"
|
||||||
|
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
|
||||||
|
[eval $cachevar=yes],
|
||||||
|
[eval $cachevar=no])
|
||||||
|
CXX="$ac_save_CXX"])
|
||||||
|
if eval test x\$$cachevar = xyes; then
|
||||||
|
CXX="$CXX $switch"
|
||||||
|
if test -n "$CXXCPP" ; then
|
||||||
|
CXXCPP="$CXXCPP $switch"
|
||||||
|
fi
|
||||||
|
ac_success=yes
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi])
|
||||||
|
|
||||||
|
m4_if([$2], [ext], [], [dnl
|
||||||
|
if test x$ac_success = xno; then
|
||||||
|
dnl HP's aCC needs +std=c++11 according to:
|
||||||
|
dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf
|
||||||
|
dnl Cray's crayCC needs "-h std=c++11"
|
||||||
|
for alternative in ${ax_cxx_compile_alternatives}; do
|
||||||
|
for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do
|
||||||
|
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
|
||||||
|
AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
|
||||||
|
$cachevar,
|
||||||
|
[ac_save_CXX="$CXX"
|
||||||
|
CXX="$CXX $switch"
|
||||||
|
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
|
||||||
|
[eval $cachevar=yes],
|
||||||
|
[eval $cachevar=no])
|
||||||
|
CXX="$ac_save_CXX"])
|
||||||
|
if eval test x\$$cachevar = xyes; then
|
||||||
|
CXX="$CXX $switch"
|
||||||
|
if test -n "$CXXCPP" ; then
|
||||||
|
CXXCPP="$CXXCPP $switch"
|
||||||
|
fi
|
||||||
|
ac_success=yes
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if test x$ac_success = xyes; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi])
|
||||||
|
AC_LANG_POP([C++])
|
||||||
|
if test x$ax_cxx_compile_cxx$1_required = xtrue; then
|
||||||
|
if test x$ac_success = xno; then
|
||||||
|
AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.])
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if test x$ac_success = xno; then
|
||||||
|
HAVE_CXX$1=0
|
||||||
|
AC_MSG_NOTICE([No compiler with C++$1 support was found])
|
||||||
|
else
|
||||||
|
HAVE_CXX$1=1
|
||||||
|
AC_DEFINE(HAVE_CXX$1,1,
|
||||||
|
[define if the compiler supports basic C++$1 syntax])
|
||||||
|
fi
|
||||||
|
AC_SUBST(HAVE_CXX$1)
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
dnl Test body for checking C++11 support
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11],
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
dnl Test body for checking C++14 support
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_14
|
||||||
|
)
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17],
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_14
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_17
|
||||||
|
)
|
||||||
|
|
||||||
|
dnl Tests for new features in C++11
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[
|
||||||
|
|
||||||
|
// If the compiler admits that it is not ready for C++11, why torture it?
|
||||||
|
// Hopefully, this will speed up the test.
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
|
||||||
|
#error "This is not a C++ compiler"
|
||||||
|
|
||||||
|
#elif __cplusplus < 201103L
|
||||||
|
|
||||||
|
#error "This is not a C++11 compiler"
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
namespace cxx11
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace test_static_assert
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct check
|
||||||
|
{
|
||||||
|
static_assert(sizeof(int) <= sizeof(T), "not big enough");
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_final_override
|
||||||
|
{
|
||||||
|
|
||||||
|
struct Base
|
||||||
|
{
|
||||||
|
virtual void f() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Derived : public Base
|
||||||
|
{
|
||||||
|
virtual void f() override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_double_right_angle_brackets
|
||||||
|
{
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
struct check {};
|
||||||
|
|
||||||
|
typedef check<void> single_type;
|
||||||
|
typedef check<check<void>> double_type;
|
||||||
|
typedef check<check<check<void>>> triple_type;
|
||||||
|
typedef check<check<check<check<void>>>> quadruple_type;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_decltype
|
||||||
|
{
|
||||||
|
|
||||||
|
int
|
||||||
|
f()
|
||||||
|
{
|
||||||
|
int a = 1;
|
||||||
|
decltype(a) b = 2;
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_type_deduction
|
||||||
|
{
|
||||||
|
|
||||||
|
template < typename T1, typename T2 >
|
||||||
|
struct is_same
|
||||||
|
{
|
||||||
|
static const bool value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
struct is_same<T, T>
|
||||||
|
{
|
||||||
|
static const bool value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
template < typename T1, typename T2 >
|
||||||
|
auto
|
||||||
|
add(T1 a1, T2 a2) -> decltype(a1 + a2)
|
||||||
|
{
|
||||||
|
return a1 + a2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
test(const int c, volatile int v)
|
||||||
|
{
|
||||||
|
static_assert(is_same<int, decltype(0)>::value == true, "");
|
||||||
|
static_assert(is_same<int, decltype(c)>::value == false, "");
|
||||||
|
static_assert(is_same<int, decltype(v)>::value == false, "");
|
||||||
|
auto ac = c;
|
||||||
|
auto av = v;
|
||||||
|
auto sumi = ac + av + 'x';
|
||||||
|
auto sumf = ac + av + 1.0;
|
||||||
|
static_assert(is_same<int, decltype(ac)>::value == true, "");
|
||||||
|
static_assert(is_same<int, decltype(av)>::value == true, "");
|
||||||
|
static_assert(is_same<int, decltype(sumi)>::value == true, "");
|
||||||
|
static_assert(is_same<int, decltype(sumf)>::value == false, "");
|
||||||
|
static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
|
||||||
|
return (sumf > 0.0) ? sumi : add(c, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_noexcept
|
||||||
|
{
|
||||||
|
|
||||||
|
int f() { return 0; }
|
||||||
|
int g() noexcept { return 0; }
|
||||||
|
|
||||||
|
static_assert(noexcept(f()) == false, "");
|
||||||
|
static_assert(noexcept(g()) == true, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_constexpr
|
||||||
|
{
|
||||||
|
|
||||||
|
template < typename CharT >
|
||||||
|
unsigned long constexpr
|
||||||
|
strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
|
||||||
|
{
|
||||||
|
return *s ? strlen_c_r(s + 1, acc + 1) : acc;
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename CharT >
|
||||||
|
unsigned long constexpr
|
||||||
|
strlen_c(const CharT *const s) noexcept
|
||||||
|
{
|
||||||
|
return strlen_c_r(s, 0UL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static_assert(strlen_c("") == 0UL, "");
|
||||||
|
static_assert(strlen_c("1") == 1UL, "");
|
||||||
|
static_assert(strlen_c("example") == 7UL, "");
|
||||||
|
static_assert(strlen_c("another\0example") == 7UL, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_rvalue_references
|
||||||
|
{
|
||||||
|
|
||||||
|
template < int N >
|
||||||
|
struct answer
|
||||||
|
{
|
||||||
|
static constexpr int value = N;
|
||||||
|
};
|
||||||
|
|
||||||
|
answer<1> f(int&) { return answer<1>(); }
|
||||||
|
answer<2> f(const int&) { return answer<2>(); }
|
||||||
|
answer<3> f(int&&) { return answer<3>(); }
|
||||||
|
|
||||||
|
void
|
||||||
|
test()
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
const int c = 0;
|
||||||
|
static_assert(decltype(f(i))::value == 1, "");
|
||||||
|
static_assert(decltype(f(c))::value == 2, "");
|
||||||
|
static_assert(decltype(f(0))::value == 3, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_uniform_initialization
|
||||||
|
{
|
||||||
|
|
||||||
|
struct test
|
||||||
|
{
|
||||||
|
static const int zero {};
|
||||||
|
static const int one {1};
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(test::zero == 0, "");
|
||||||
|
static_assert(test::one == 1, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_lambdas
|
||||||
|
{
|
||||||
|
|
||||||
|
void
|
||||||
|
test1()
|
||||||
|
{
|
||||||
|
auto lambda1 = [](){};
|
||||||
|
auto lambda2 = lambda1;
|
||||||
|
lambda1();
|
||||||
|
lambda2();
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
test2()
|
||||||
|
{
|
||||||
|
auto a = [](int i, int j){ return i + j; }(1, 2);
|
||||||
|
auto b = []() -> int { return '0'; }();
|
||||||
|
auto c = [=](){ return a + b; }();
|
||||||
|
auto d = [&](){ return c; }();
|
||||||
|
auto e = [a, &b](int x) mutable {
|
||||||
|
const auto identity = [](int y){ return y; };
|
||||||
|
for (auto i = 0; i < a; ++i)
|
||||||
|
a += b--;
|
||||||
|
return x + identity(a + b);
|
||||||
|
}(0);
|
||||||
|
return a + b + c + d + e;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
test3()
|
||||||
|
{
|
||||||
|
const auto nullary = [](){ return 0; };
|
||||||
|
const auto unary = [](int x){ return x; };
|
||||||
|
using nullary_t = decltype(nullary);
|
||||||
|
using unary_t = decltype(unary);
|
||||||
|
const auto higher1st = [](nullary_t f){ return f(); };
|
||||||
|
const auto higher2nd = [unary](nullary_t f1){
|
||||||
|
return [unary, f1](unary_t f2){ return f2(unary(f1())); };
|
||||||
|
};
|
||||||
|
return higher1st(nullary) + higher2nd(nullary)(unary);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_variadic_templates
|
||||||
|
{
|
||||||
|
|
||||||
|
template <int...>
|
||||||
|
struct sum;
|
||||||
|
|
||||||
|
template <int N0, int... N1toN>
|
||||||
|
struct sum<N0, N1toN...>
|
||||||
|
{
|
||||||
|
static constexpr auto value = N0 + sum<N1toN...>::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct sum<>
|
||||||
|
{
|
||||||
|
static constexpr auto value = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sum<>::value == 0, "");
|
||||||
|
static_assert(sum<1>::value == 1, "");
|
||||||
|
static_assert(sum<23>::value == 23, "");
|
||||||
|
static_assert(sum<1, 2>::value == 3, "");
|
||||||
|
static_assert(sum<5, 5, 11>::value == 21, "");
|
||||||
|
static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
|
||||||
|
// Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
|
||||||
|
// because of this.
|
||||||
|
namespace test_template_alias_sfinae
|
||||||
|
{
|
||||||
|
|
||||||
|
struct foo {};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using member = typename T::member_type;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void func(...) {}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void func(member<T>*) {}
|
||||||
|
|
||||||
|
void test();
|
||||||
|
|
||||||
|
void test() { func<foo>(0); }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cxx11
|
||||||
|
|
||||||
|
#endif // __cplusplus >= 201103L
|
||||||
|
|
||||||
|
]])
|
||||||
|
|
||||||
|
|
||||||
|
dnl Tests for new features in C++14
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[
|
||||||
|
|
||||||
|
// If the compiler admits that it is not ready for C++14, why torture it?
|
||||||
|
// Hopefully, this will speed up the test.
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
|
||||||
|
#error "This is not a C++ compiler"
|
||||||
|
|
||||||
|
#elif __cplusplus < 201402L
|
||||||
|
|
||||||
|
#error "This is not a C++14 compiler"
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
namespace cxx14
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace test_polymorphic_lambdas
|
||||||
|
{
|
||||||
|
|
||||||
|
int
|
||||||
|
test()
|
||||||
|
{
|
||||||
|
const auto lambda = [](auto&&... args){
|
||||||
|
const auto istiny = [](auto x){
|
||||||
|
return (sizeof(x) == 1UL) ? 1 : 0;
|
||||||
|
};
|
||||||
|
const int aretiny[] = { istiny(args)... };
|
||||||
|
return aretiny[0];
|
||||||
|
};
|
||||||
|
return lambda(1, 1L, 1.0f, '1');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_binary_literals
|
||||||
|
{
|
||||||
|
|
||||||
|
constexpr auto ivii = 0b0000000000101010;
|
||||||
|
static_assert(ivii == 42, "wrong value");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_generalized_constexpr
|
||||||
|
{
|
||||||
|
|
||||||
|
template < typename CharT >
|
||||||
|
constexpr unsigned long
|
||||||
|
strlen_c(const CharT *const s) noexcept
|
||||||
|
{
|
||||||
|
auto length = 0UL;
|
||||||
|
for (auto p = s; *p; ++p)
|
||||||
|
++length;
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
static_assert(strlen_c("") == 0UL, "");
|
||||||
|
static_assert(strlen_c("x") == 1UL, "");
|
||||||
|
static_assert(strlen_c("test") == 4UL, "");
|
||||||
|
static_assert(strlen_c("another\0test") == 7UL, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_lambda_init_capture
|
||||||
|
{
|
||||||
|
|
||||||
|
int
|
||||||
|
test()
|
||||||
|
{
|
||||||
|
auto x = 0;
|
||||||
|
const auto lambda1 = [a = x](int b){ return a + b; };
|
||||||
|
const auto lambda2 = [a = lambda1(x)](){ return a; };
|
||||||
|
return lambda2();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_digit_separators
|
||||||
|
{
|
||||||
|
|
||||||
|
constexpr auto ten_million = 100'000'000;
|
||||||
|
static_assert(ten_million == 100000000, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_return_type_deduction
|
||||||
|
{
|
||||||
|
|
||||||
|
auto f(int& x) { return x; }
|
||||||
|
decltype(auto) g(int& x) { return x; }
|
||||||
|
|
||||||
|
template < typename T1, typename T2 >
|
||||||
|
struct is_same
|
||||||
|
{
|
||||||
|
static constexpr auto value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
struct is_same<T, T>
|
||||||
|
{
|
||||||
|
static constexpr auto value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
test()
|
||||||
|
{
|
||||||
|
auto x = 0;
|
||||||
|
static_assert(is_same<int, decltype(f(x))>::value, "");
|
||||||
|
static_assert(is_same<int&, decltype(g(x))>::value, "");
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cxx14
|
||||||
|
|
||||||
|
#endif // __cplusplus >= 201402L
|
||||||
|
|
||||||
|
]])
|
||||||
|
|
||||||
|
|
||||||
|
dnl Tests for new features in C++17
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[
|
||||||
|
|
||||||
|
// If the compiler admits that it is not ready for C++17, why torture it?
|
||||||
|
// Hopefully, this will speed up the test.
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
|
||||||
|
#error "This is not a C++ compiler"
|
||||||
|
|
||||||
|
#elif __cplusplus <= 201402L
|
||||||
|
|
||||||
|
#error "This is not a C++17 compiler"
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
#define REALLY_CLANG
|
||||||
|
#else
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
#define REALLY_GCC
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <initializer_list>
|
||||||
|
#include <utility>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace cxx17
|
||||||
|
{
|
||||||
|
|
||||||
|
#if !defined(REALLY_CLANG)
|
||||||
|
namespace test_constexpr_lambdas
|
||||||
|
{
|
||||||
|
|
||||||
|
// TODO: test it with clang++ from git
|
||||||
|
|
||||||
|
constexpr int foo = [](){return 42;}();
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif // !defined(REALLY_CLANG)
|
||||||
|
|
||||||
|
namespace test::nested_namespace::definitions
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_fold_expression
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
int multiply(Args... args)
|
||||||
|
{
|
||||||
|
return (args * ... * 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
bool all(Args... args)
|
||||||
|
{
|
||||||
|
return (args && ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_extended_static_assert
|
||||||
|
{
|
||||||
|
|
||||||
|
static_assert (true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_auto_brace_init_list
|
||||||
|
{
|
||||||
|
|
||||||
|
auto foo = {5};
|
||||||
|
auto bar {5};
|
||||||
|
|
||||||
|
static_assert(std::is_same<std::initializer_list<int>, decltype(foo)>::value);
|
||||||
|
static_assert(std::is_same<int, decltype(bar)>::value);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_typename_in_template_template_parameter
|
||||||
|
{
|
||||||
|
|
||||||
|
template<template<typename> typename X> struct D;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_fallthrough_nodiscard_maybe_unused_attributes
|
||||||
|
{
|
||||||
|
|
||||||
|
int f1()
|
||||||
|
{
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] int f2()
|
||||||
|
{
|
||||||
|
[[maybe_unused]] auto unused = f1();
|
||||||
|
|
||||||
|
switch (f1())
|
||||||
|
{
|
||||||
|
case 17:
|
||||||
|
f1();
|
||||||
|
[[fallthrough]];
|
||||||
|
case 42:
|
||||||
|
f1();
|
||||||
|
}
|
||||||
|
return f1();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_extended_aggregate_initialization
|
||||||
|
{
|
||||||
|
|
||||||
|
struct base1
|
||||||
|
{
|
||||||
|
int b1, b2 = 42;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct base2
|
||||||
|
{
|
||||||
|
base2() {
|
||||||
|
b3 = 42;
|
||||||
|
}
|
||||||
|
int b3;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct derived : base1, base2
|
||||||
|
{
|
||||||
|
int d;
|
||||||
|
};
|
||||||
|
|
||||||
|
derived d1 {{1, 2}, {}, 4}; // full initialization
|
||||||
|
derived d2 {{}, {}, 4}; // value-initialized bases
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_general_range_based_for_loop
|
||||||
|
{
|
||||||
|
|
||||||
|
struct iter
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
int& operator* ()
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int& operator* () const
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
iter& operator++()
|
||||||
|
{
|
||||||
|
++i;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sentinel
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool operator== (const iter& i, const sentinel& s)
|
||||||
|
{
|
||||||
|
return i.i == s.i;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!= (const iter& i, const sentinel& s)
|
||||||
|
{
|
||||||
|
return !(i == s);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct range
|
||||||
|
{
|
||||||
|
iter begin() const
|
||||||
|
{
|
||||||
|
return {0};
|
||||||
|
}
|
||||||
|
|
||||||
|
sentinel end() const
|
||||||
|
{
|
||||||
|
return {5};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void f()
|
||||||
|
{
|
||||||
|
range r {};
|
||||||
|
|
||||||
|
for (auto i : r)
|
||||||
|
{
|
||||||
|
[[maybe_unused]] auto v = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_lambda_capture_asterisk_this_by_value
|
||||||
|
{
|
||||||
|
|
||||||
|
struct t
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int foo()
|
||||||
|
{
|
||||||
|
return [*this]()
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_enum_class_construction
|
||||||
|
{
|
||||||
|
|
||||||
|
enum class byte : unsigned char
|
||||||
|
{};
|
||||||
|
|
||||||
|
byte foo {42};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_constexpr_if
|
||||||
|
{
|
||||||
|
|
||||||
|
template <bool cond>
|
||||||
|
int f ()
|
||||||
|
{
|
||||||
|
if constexpr(cond)
|
||||||
|
{
|
||||||
|
return 13;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_selection_statement_with_initializer
|
||||||
|
{
|
||||||
|
|
||||||
|
int f()
|
||||||
|
{
|
||||||
|
return 13;
|
||||||
|
}
|
||||||
|
|
||||||
|
int f2()
|
||||||
|
{
|
||||||
|
if (auto i = f(); i > 0)
|
||||||
|
{
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (auto i = f(); i + 4)
|
||||||
|
{
|
||||||
|
case 17:
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(REALLY_CLANG)
|
||||||
|
namespace test_template_argument_deduction_for_class_templates
|
||||||
|
{
|
||||||
|
|
||||||
|
// TODO: test it with clang++ from git
|
||||||
|
|
||||||
|
template <typename T1, typename T2>
|
||||||
|
struct pair
|
||||||
|
{
|
||||||
|
pair (T1 p1, T2 p2)
|
||||||
|
: m1 {p1},
|
||||||
|
m2 {p2}
|
||||||
|
{}
|
||||||
|
|
||||||
|
T1 m1;
|
||||||
|
T2 m2;
|
||||||
|
};
|
||||||
|
|
||||||
|
void f()
|
||||||
|
{
|
||||||
|
[[maybe_unused]] auto p = pair{13, 42u};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif // !defined(REALLY_CLANG)
|
||||||
|
|
||||||
|
namespace test_non_type_auto_template_parameters
|
||||||
|
{
|
||||||
|
|
||||||
|
template <auto n>
|
||||||
|
struct B
|
||||||
|
{};
|
||||||
|
|
||||||
|
B<5> b1;
|
||||||
|
B<'a'> b2;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(REALLY_CLANG)
|
||||||
|
namespace test_structured_bindings
|
||||||
|
{
|
||||||
|
|
||||||
|
// TODO: test it with clang++ from git
|
||||||
|
|
||||||
|
int arr[2] = { 1, 2 };
|
||||||
|
std::pair<int, int> pr = { 1, 2 };
|
||||||
|
|
||||||
|
auto f1() -> int(&)[2]
|
||||||
|
{
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto f2() -> std::pair<int, int>&
|
||||||
|
{
|
||||||
|
return pr;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct S
|
||||||
|
{
|
||||||
|
int x1 : 2;
|
||||||
|
volatile double y1;
|
||||||
|
};
|
||||||
|
|
||||||
|
S f3()
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto [ x1, y1 ] = f1();
|
||||||
|
auto& [ xr1, yr1 ] = f1();
|
||||||
|
auto [ x2, y2 ] = f2();
|
||||||
|
auto& [ xr2, yr2 ] = f2();
|
||||||
|
const auto [ x3, y3 ] = f3();
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif // !defined(REALLY_CLANG)
|
||||||
|
|
||||||
|
#if !defined(REALLY_CLANG)
|
||||||
|
namespace test_exception_spec_type_system
|
||||||
|
{
|
||||||
|
|
||||||
|
// TODO: test it with clang++ from git
|
||||||
|
|
||||||
|
struct Good {};
|
||||||
|
struct Bad {};
|
||||||
|
|
||||||
|
void g1() noexcept;
|
||||||
|
void g2();
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
Bad
|
||||||
|
f(T*, T*);
|
||||||
|
|
||||||
|
template<typename T1, typename T2>
|
||||||
|
Good
|
||||||
|
f(T1*, T2*);
|
||||||
|
|
||||||
|
static_assert (std::is_same_v<Good, decltype(f(g1, g2))>);
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif // !defined(REALLY_CLANG)
|
||||||
|
|
||||||
|
namespace test_inline_variables
|
||||||
|
{
|
||||||
|
|
||||||
|
template<class T> void f(T)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template<class T> inline T g(T)
|
||||||
|
{
|
||||||
|
return T{};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<> inline void f<>(int)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template<> int g<>(int)
|
||||||
|
{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cxx17
|
||||||
|
|
||||||
|
#endif // __cplusplus <= 201402L
|
||||||
|
|
||||||
|
]])
|
10
Frameworks/OpenMPT/OpenMPT/contrib/libmodplug-0.8.8.5/test.sh
Executable file
10
Frameworks/OpenMPT/OpenMPT/contrib/libmodplug-0.8.8.5/test.sh
Executable file
|
@ -0,0 +1,10 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
./autogen.sh
|
||||||
|
|
||||||
|
./configure
|
||||||
|
make
|
||||||
|
make distcheck
|
||||||
|
make distclean
|
|
@ -0,0 +1,26 @@
|
||||||
|
Copyright (c) 2004-2020, OpenMPT contributors
|
||||||
|
Copyright (c) 1997-2003, Olivier Lapicque
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of the OpenMPT project nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
|
||||||
|
ACLOCAL_AMFLAGS = -I m4 --install
|
||||||
|
EXTRA_DIST =
|
||||||
|
EXTRA_DIST += LICENSE
|
||||||
|
EXTRA_DIST += libopenmpt_modplug.pc.in
|
||||||
|
EXTRA_DIST += libmodplug.pc.in
|
||||||
|
EXTRA_DIST += test.sh
|
||||||
|
MOSTLYCLEANFILES =
|
||||||
|
|
||||||
|
dist_doc_DATA =
|
||||||
|
dist_doc_DATA += LICENSE
|
||||||
|
nobase_dist_doc_DATA =
|
||||||
|
|
||||||
|
bin_PROGRAMS =
|
||||||
|
check_PROGRAMS =
|
||||||
|
lib_LTLIBRARIES =
|
||||||
|
|
||||||
|
pkgconfigdir = $(libdir)/pkgconfig
|
||||||
|
pkgconfig_DATA =
|
||||||
|
nobase_include_HEADERS =
|
||||||
|
|
||||||
|
if ENABLE_LIBOPENMPT_MODPLUG
|
||||||
|
lib_LTLIBRARIES += libopenmpt_modplug.la
|
||||||
|
libopenmpt_modplug_la_LDFLAGS = -version-info 1:0:0 -no-undefined
|
||||||
|
libopenmpt_modplug_la_CPPFLAGS = -I$(srcdir)/ $(LIBOPENMPT_CPPFLAGS)
|
||||||
|
libopenmpt_modplug_la_CXXFLAGS = $(LIBOPENMPT_CFLAGS)
|
||||||
|
libopenmpt_modplug_la_CFLAGS = $(LIBOPENMPT_CFLAGS)
|
||||||
|
libopenmpt_modplug_la_LIBADD = $(LIBOPENMPT_LIBS)
|
||||||
|
libopenmpt_modplug_la_SOURCES =
|
||||||
|
libopenmpt_modplug_la_SOURCES += libopenmpt_modplug.c
|
||||||
|
libopenmpt_modplug_la_SOURCES += libopenmpt_modplug_cpp.cpp
|
||||||
|
endif
|
||||||
|
|
||||||
|
if ENABLE_LIBMODPLUG
|
||||||
|
pkgconfig_DATA += libmodplug.pc
|
||||||
|
lib_LTLIBRARIES += libmodplug.la
|
||||||
|
libmodplug_la_LDFLAGS = -version-info 1:0:0 -no-undefined
|
||||||
|
nobase_include_HEADERS += libmodplug/modplug.h libmodplug/sndfile.h libmodplug/stdafx.h
|
||||||
|
libmodplug_la_CPPFLAGS = -I$(srcdir)/ $(LIBOPENMPT_CPPFLAGS)
|
||||||
|
libmodplug_la_CXXFLAGS = $(LIBOPENMPT_CFLAGS)
|
||||||
|
libmodplug_la_CFLAGS = $(LIBOPENMPT_CFLAGS)
|
||||||
|
libmodplug_la_LIBADD = $(LIBOPENMPT_LIBS)
|
||||||
|
libmodplug_la_SOURCES =
|
||||||
|
libmodplug_la_SOURCES += libopenmpt_modplug.c
|
||||||
|
libmodplug_la_SOURCES += libopenmpt_modplug_cpp.cpp
|
||||||
|
endif
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue