Updated libopenmpt to version 0.5.2

This commit is contained in:
Christopher Snowhill 2020-09-21 21:54:24 -07:00
parent 640e8b7304
commit dab78ed74f
327 changed files with 23363 additions and 15401 deletions

View file

@ -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.

View file

@ -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 $< > $@

View file

@ -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

View file

@ -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 \

View file

@ -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

View file

@ -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.

View file

@ -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

View 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

View file

@ -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=

View file

@ -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)

View file

@ -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

View file

@ -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.

View 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=

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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();
} }

View file

@ -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));

View file

@ -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

View file

@ -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 ];

View file

@ -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

View file

@ -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;
} }

View file

@ -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)); }

View file

@ -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

View file

@ -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; }
};

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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();
}; };

View file

@ -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

View file

@ -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);
} }
}; };

View file

@ -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;

View file

@ -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);

View file

@ -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)

View file

@ -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

View file

@ -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
} }

View file

@ -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

View 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

View 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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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()();
} }
}; };

View file

@ -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

View file

@ -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>;

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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();

View file

@ -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) { }

View file

@ -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> >()

View file

@ -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));
} }

View file

@ -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))));

View file

@ -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"

View file

@ -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"

View file

@ -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())}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -0,0 +1,2 @@
#!/usr/bin/env sh
autoreconf -i

View file

@ -0,0 +1,7 @@
#!/usr/bin/env bash
set -e
./autogen.sh
./configure
make distclean

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,9 @@
#!/usr/bin/env bash
set -e
./test.sh
./autogen.sh
./configure
make dist

View file

@ -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:

View file

@ -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>

View file

@ -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}

View file

@ -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>

View file

@ -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
]])

View file

@ -0,0 +1,10 @@
#!/usr/bin/env bash
set -e
./autogen.sh
./configure
make
make distcheck
make distclean

View file

@ -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.

View file

@ -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