Index: build-aux/m4/buildsys.m4 ================================================================== --- build-aux/m4/buildsys.m4 +++ build-aux/m4/buildsys.m4 @@ -20,10 +20,13 @@ dnl CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) dnl ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE dnl POSSIBILITY OF SUCH DAMAGE. dnl +AC_ARG_ENABLE(rpath, + AS_HELP_STRING([--disable-rpath], [do not use rpath])) + AC_DEFUN([BUILDSYS_INIT], [ AC_REQUIRE([AC_CANONICAL_BUILD]) AC_REQUIRE([AC_CANONICAL_HOST]) case "$build_os" in @@ -180,11 +183,13 @@ LIB_CFLAGS='-fPIC -DPIC' LIB_LDFLAGS='-dynamiclib -current_version ${LIB_MAJOR}.${LIB_MINOR} -compatibility_version ${LIB_MAJOR}' LIB_LDFLAGS_INSTALL_NAME='-Wl,-install_name,${libdir}/$${out%.dylib}.${LIB_MAJOR}.dylib' LIB_PREFIX='lib' LIB_SUFFIX='.dylib' - LDFLAGS_RPATH='-Wl,-rpath,${libdir}' + AS_IF([test x"$enable_rpath" != x"no"], [ + LDFLAGS_RPATH='-Wl,-rpath,${libdir}' + ]) PLUGIN_CFLAGS='-fPIC -DPIC' PLUGIN_LDFLAGS='-bundle ${PLUGIN_LDFLAGS_BUNDLE_LOADER}' PLUGIN_SUFFIX='.bundle' AS_IF([test x"$host_is_ios" = x"yes"], [ LINK_PLUGIN='rm -fr $$out && ${MKDIR_P} $$out && if test -f Info.plist; then ${INSTALL} -m 644 Info.plist $$out/Info.plist; fi && ${LD} -o $$out/$${out%${PLUGIN_SUFFIX}} ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS} && ${CODESIGN} -fs ${CODESIGN_IDENTITY} --timestamp=none $$out' @@ -198,20 +203,22 @@ CLEAN_LIB='' ;; *-*-mingw* | *-*-cygwin*) AC_MSG_RESULT(MinGW / Cygwin) LIB_CFLAGS='' - LIB_LDFLAGS='-shared -Wl,--export-all-symbols,--out-implib,lib$$out.a' + LIB_LDFLAGS='-shared -Wl,--export-all-symbols,--out-implib,lib$${out%${LIB_SUFFIX}}.a' LIB_LDFLAGS_INSTALL_NAME='' LIB_PREFIX='' - LIB_SUFFIX='.dll' - LDFLAGS_RPATH='-Wl,-rpath,${libdir}' + LIB_SUFFIX='${LIB_MAJOR}.dll' + AS_IF([test x"$enable_rpath" != x"no"], [ + LDFLAGS_RPATH='-Wl,-rpath,${libdir}' + ]) PLUGIN_CFLAGS='' PLUGIN_LDFLAGS='-shared' PLUGIN_SUFFIX='.dll' LINK_PLUGIN='${LD} -o $$out ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS}' - INSTALL_LIB='&& ${MKDIR_P} ${DESTDIR}${bindir} && ${INSTALL} -m 755 $$i ${DESTDIR}${bindir}/$$i && ${INSTALL} -m 755 lib$$i.a ${DESTDIR}${libdir}/lib$$i.a' + INSTALL_LIB='&& ${MKDIR_P} ${DESTDIR}${bindir} && ${INSTALL} -m 755 $$i ${DESTDIR}${bindir}/$$i && ${INSTALL} -m 755 lib$${i%${LIB_SUFFIX}}.a ${DESTDIR}${libdir}/lib$${i%${LIB_SUFFIX}}.a' UNINSTALL_LIB='&& rm -f ${DESTDIR}${bindir}/$$i ${DESTDIR}${libdir}/lib$$i.a' INSTALL_PLUGIN='&& ${INSTALL} -m 755 $$i ${DESTDIR}${plugindir}/$$i' UNINSTALL_PLUGIN='&& rm -f ${DESTDIR}${plugindir}/$$i' CLEAN_LIB='${SHARED_LIB}.a ${SHARED_LIB_NOINST}.a' ;; @@ -220,11 +227,13 @@ LIB_CFLAGS='-fPIC -DPIC' LIB_LDFLAGS='-shared' LIB_LDFLAGS_INSTALL_NAME='' LIB_PREFIX='lib' LIB_SUFFIX='.so.${LIB_MAJOR}.${LIB_MINOR}' - LDFLAGS_RPATH='-Wl,-rpath,${libdir}' + AS_IF([test x"$enable_rpath" != x"no"], [ + LDFLAGS_RPATH='-Wl,-rpath,${libdir}' + ]) PLUGIN_CFLAGS='-fPIC -DPIC' PLUGIN_LDFLAGS='-shared' PLUGIN_SUFFIX='.so' LINK_PLUGIN='${LD} -o $$out ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS}' INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$$i' @@ -238,11 +247,13 @@ LIB_CFLAGS='-fPIC -DPIC' LIB_LDFLAGS='-shared -Wl,-soname=$$out.${LIB_MAJOR}.${LIB_MINOR}' LIB_LDFLAGS_INSTALL_NAME='' LIB_PREFIX='lib' LIB_SUFFIX='.so' - LDFLAGS_RPATH='-Wl,-rpath,${libdir}' + AS_IF([test x"$enable_rpath" != x"no"], [ + LDFLAGS_RPATH='-Wl,-rpath,${libdir}' + ]) PLUGIN_CFLAGS='-fPIC -DPIC' PLUGIN_LDFLAGS='-shared' PLUGIN_SUFFIX='.so' LINK_PLUGIN='${LD} -o $$out ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS}' INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$$i.${LIB_MAJOR}.${LIB_MINOR} && rm -f ${DESTDIR}${libdir}/$$i && ${LN_S} $$i.${LIB_MAJOR}.${LIB_MINOR} ${DESTDIR}${libdir}/$$i' @@ -256,11 +267,10 @@ LIB_CFLAGS='-fPIC -DPIC' LIB_LDFLAGS='-shared -Wl,-soname=$$out.${LIB_MAJOR}' LIB_LDFLAGS_INSTALL_NAME='' LIB_PREFIX='lib' LIB_SUFFIX='.so' - LDFLAGS_RPATH='' PLUGIN_CFLAGS='-fPIC -DPIC' PLUGIN_LDFLAGS='-shared' PLUGIN_SUFFIX='.so' LINK_PLUGIN='${LD} -o $$out ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS}' INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$$i.${LIB_MAJOR}.${LIB_MINOR}.0 && ${LN_S} -f $$i.${LIB_MAJOR}.${LIB_MINOR}.0 ${DESTDIR}${libdir}/$$i.${LIB_MAJOR} && ${LN_S} -f $$i.${LIB_MAJOR}.${LIB_MINOR}.0 ${DESTDIR}${libdir}/$$i' @@ -275,11 +285,13 @@ LIB_LDFLAGS='-shared -Wl,+h,$$out' LIB_LDFLAGS_INSTALL_NAME='' LIB_PREFIX='lib' LIB_SUFFIX='.${LIB_MAJOR}' LINK_LIB='&& rm -f $${out%%.*}.sl && ${LN_S} $$out $${out%%.*}.sl' - LDFLAGS_RPATH='-Wl,+b,${libdir}' + AS_IF([test x"$enable_rpath" != x"no"], [ + LDFLAGS_RPATH='-Wl,+b,${libdir}' + ]) PLUGIN_CFLAGS='-fPIC -DPIC' PLUGIN_LDFLAGS='-shared' PLUGIN_SUFFIX='.sl' LINK_PLUGIN='${LD} -o $$out ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS}' INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$$i && ${LN_S} -f $$i ${DESTDIR}${libdir}/$${i%%.*}.sl' @@ -294,11 +306,13 @@ LIB_LDFLAGS='-shared -Wl,+h,$$out' LIB_LDFLAGS_INSTALL_NAME='' LIB_PREFIX='lib' LIB_SUFFIX='.${LIB_MAJOR}' LINK_LIB='&& rm -f $${out%%.*}.so && ${LN_S} $$out $${out%%.*}.so' - LDFLAGS_RPATH='-Wl,+b,${libdir}' + AS_IF([test x"$enable_rpath" != x"no"], [ + LDFLAGS_RPATH='-Wl,+b,${libdir}' + ]) PLUGIN_CFLAGS='-fPIC -DPIC' PLUGIN_LDFLAGS='-shared' PLUGIN_SUFFIX='.so' LINK_PLUGIN='${LD} -o $$out ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS}' INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$$i && ${LN_S} -f $$i ${DESTDIR}${libdir}/$${i%%.*}.so' @@ -312,11 +326,13 @@ LIB_CFLAGS='-fPIC -DPIC' LIB_LDFLAGS='-shared -Wl,-soname=$$out.${LIB_MAJOR}' LIB_LDFLAGS_INSTALL_NAME='' LIB_PREFIX='lib' LIB_SUFFIX='.so' - LDFLAGS_RPATH='-Wl,-rpath,${libdir}' + AS_IF([test x"$enable_rpath" != x"no"], [ + LDFLAGS_RPATH='-Wl,-rpath,${libdir}' + ]) PLUGIN_CFLAGS='-fPIC -DPIC' PLUGIN_LDFLAGS='-shared' PLUGIN_SUFFIX='.so' LINK_PLUGIN='${LD} -o $$out ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS}' INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$$i.${LIB_MAJOR}.${LIB_MINOR}.0 && ${LN_S} -f $$i.${LIB_MAJOR}.${LIB_MINOR}.0 ${DESTDIR}${libdir}/$$i.${LIB_MAJOR} && ${LN_S} -f $$i.${LIB_MAJOR}.${LIB_MINOR}.0 ${DESTDIR}${libdir}/$$i' Index: buildsys.mk.in ================================================================== --- buildsys.mk.in +++ buildsys.mk.in @@ -210,11 +210,11 @@ done if test x"${includesubdir}" = x"${COPY_HEADERS_IF_SUBDIR}"; then \ for i in "" ${INCLUDES}; do \ test x"$$i" = x"" && continue; \ - ${MKDIR_P} ${COPY_HEADERS_DESTINATION} || exit $$?; \ + ${MKDIR_P} $$(dirname ${COPY_HEADERS_DESTINATION}/$$i) || exit $$?; \ ${INSTALL} -m 644 $$i ${COPY_HEADERS_DESTINATION}/$$i || exit $$?; \ done \ fi ${AMIGA_LIB} ${AMIGA_LIB_NOINST}: ${EXT_DEPS} ${AMIGA_LIB_OBJS_START} ${AMIGA_LIB_OBJS} ${AMIGA_LIB_OBJS_EXTRA} @@ -731,11 +731,11 @@ if test x"${INSTALL_INCLUDES}" = x"yes"; then \ for i in "" ${INCLUDES}; do \ test x"$$i" = x"" && continue; \ ${INSTALL_STATUS}; \ - if ${MKDIR_P} ${DESTDIR}${includedir}/${includesubdir} && ${INSTALL} -m 644 $$i ${DESTDIR}${includedir}/${includesubdir}/$$i; then \ + if ${MKDIR_P} $$(dirname ${DESTDIR}${includedir}/${includesubdir}/$$i) && ${INSTALL} -m 644 $$i ${DESTDIR}${includedir}/${includesubdir}/$$i; then \ ${INSTALL_OK}; \ else \ ${INSTALL_FAILED}; \ fi \ done \ Index: configure.ac ================================================================== --- configure.ac +++ configure.ac @@ -46,11 +46,12 @@ enable_files="yes" # Required for reading ENV: enable_shared="no" supports_amiga_lib="yes" AS_IF([test x"$enable_amiga_lib" != x"no"], [ - AC_SUBST(OBJFWRT_AMIGA_LIB, objfwrt68k.library) + AC_SUBST(OBJFWRT_AMIGA_LIB, + ['objfwrt${OBJFWRT_LIB_MAJOR}.library']) dnl For 68000, GCC emits calls to helper functions that dnl do not work properly in a library. t="-mcpu=68020 -fbaserel -noixemul -ffreestanding" AC_SUBST(AMIGA_LIB_CFLAGS, $t) t="$t -resident -nostartfiles -nodefaultlibs -ldebug -lc" @@ -77,11 +78,12 @@ enable_files="yes" # Required for reading ENV: enable_shared="no" supports_amiga_lib="yes" AS_IF([test x"$enable_amiga_lib" != x"no"], [ - AC_SUBST(OBJFWRT_AMIGA_LIB, objfwrt.library) + AC_SUBST(OBJFWRT_AMIGA_LIB, + ['objfwrt${OBJFW_LIB_MAJOR}ppc.library']) t="-mresident32 -ffreestanding -noixemul" AC_SUBST(AMIGA_LIB_CFLAGS, $t) t="-mresident32 -nostartfiles -nodefaultlibs -noixemul -ldebug" AC_SUBST(AMIGA_LIB_LDFLAGS, "$t -lc") ]) @@ -1361,10 +1363,13 @@ #endif ], [ AC_DEFINE(OF_HAVE_IPV6, 1, [Whether we have IPv6]) ]) ], [ + dnl Work around a bug in autoconf 2.61 that creates a broken + dnl configure if this branch is empty. + : ], [ #ifdef _WIN32 typedef int BOOL; #endif @@ -1822,10 +1827,15 @@ __attribute__((__objc_root_class__)) # endif #endif @interface Test @end + + /** + * @struct Foo conftest.m conftest.m + */ + typedef struct {} Foo; ]) ], [ AC_MSG_RESULT(yes) ], [ AC_MSG_RESULT(no) Index: extra.mk.in ================================================================== --- extra.mk.in +++ extra.mk.in @@ -1,9 +1,9 @@ OBJFW_SHARED_LIB = @OBJFW_SHARED_LIB@ OBJFW_STATIC_LIB = @OBJFW_STATIC_LIB@ OBJFW_FRAMEWORK = @OBJFW_FRAMEWORK@ -OBJFW_LIB_MAJOR = 9 +OBJFW_LIB_MAJOR = 1 OBJFW_LIB_MINOR = 0 OBJFW_LIB_MAJOR_MINOR = ${OBJFW_LIB_MAJOR}.${OBJFW_LIB_MINOR} OBJFWRT_SHARED_LIB = @OBJFWRT_SHARED_LIB@ OBJFWRT_STATIC_LIB = @OBJFWRT_STATIC_LIB@ Index: generators/library/FuncArrayGenerator.m ================================================================== --- generators/library/FuncArrayGenerator.m +++ generators/library/FuncArrayGenerator.m @@ -65,14 +65,14 @@ - (void)generate { [_include writeString: COPYRIGHT]; [_include writeString: - @"/* This file is automatically generated from library.xml */\n" - @"\n"]; + @"/* This file is automatically generated from amiga-library.xml */" + @"\n\n"]; for (OFXMLElement *function in [_library elementsForName: @"function"]) [_include writeFormat: @"(CONST_APTR)glue_%@,\n", [function attributeForName: @"name"].stringValue]; } @end Index: generators/library/GlueGenerator.m ================================================================== --- generators/library/GlueGenerator.m +++ generators/library/GlueGenerator.m @@ -70,16 +70,16 @@ { [_header writeString: COPYRIGHT]; [_impl writeString: COPYRIGHT]; [_header writeString: - @"/* This file is automatically generated from library.xml */\n" - @"\n"]; + @"/* This file is automatically generated from amiga-library.xml */" + @"\n\n"]; [_impl writeString: - @"/* This file is automatically generated from library.xml */\n" - @"\n" + @"/* This file is automatically generated from amiga-library.xml */" + @"\n\n" @"#include \"config.h\"\n" @"\n" @"#import \"amiga-glue.h\"\n" @"\n"]; Index: generators/library/LibraryGenerator.m ================================================================== --- generators/library/LibraryGenerator.m +++ generators/library/LibraryGenerator.m @@ -34,11 +34,11 @@ - (void)applicationDidFinishLaunching { OFURL *sourcesURL = [[OFFileManager defaultManager].currentDirectoryURL URLByAppendingPathComponent: @"../../src"]; OFURL *runtimeLibraryURL = [sourcesURL - URLByAppendingPathComponent: @"runtime/library.xml"]; + URLByAppendingPathComponent: @"runtime/amiga-library.xml"]; OFURL *runtimeLinkLibURL = [sourcesURL URLByAppendingPathComponent: @"runtime/linklib/linklib.m"]; OFURL *runtimeGlueHeaderURL = [sourcesURL URLByAppendingPathComponent: @"runtime/amiga-glue.h"]; OFURL *runtimeGlueURL = [sourcesURL Index: generators/library/LinkLibGenerator.m ================================================================== --- generators/library/LinkLibGenerator.m +++ generators/library/LinkLibGenerator.m @@ -69,12 +69,12 @@ OFArray OF_GENERIC(OFXMLElement *) *functions; size_t funcIndex = 0; [_impl writeString: COPYRIGHT]; [_impl writeString: - @"/* This file is automatically generated from library.xml */\n" - @"\n" + @"/* This file is automatically generated from amiga-library.xml */" + @"\n\n" @"#include \"config.h\"\n" @"\n"]; for (OFXMLElement *include in [_library elementsForName: @"include"]) [_impl writeFormat: @"#import \"%@\"\n", Index: generators/library/Makefile ================================================================== --- generators/library/Makefile +++ generators/library/Makefile @@ -8,25 +8,27 @@ .PHONY: run run: all rm -f libobjfw.so.${OBJFW_LIB_MAJOR} rm -f libobjfw.so.${OBJFW_LIB_MAJOR_MINOR} - rm -f objfw.dll libobjfw.${OBJFW_LIB_MAJOR}.dylib + rm -f objfw${OBJFW_LIB_MAJOR}.dll libobjfw.${OBJFW_LIB_MAJOR}.dylib rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR} rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR} - rm -f objfwrt.dll libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib + rm -f objfwrt${OBJFWRT_LIB_MAJOR}.dll + rm -f libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib rm -f ${OBJFWRT_AMIGA_LIB} if test -f ../../src/libobjfw.so; then \ ${LN_S} ../../src/libobjfw.so libobjfw.so.${OBJFW_LIB_MAJOR}; \ ${LN_S} ../../src/libobjfw.so \ libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; \ elif test -f ../../src/libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; then \ ${LN_S} ../../src/libobjfw.so.${OBJFW_LIB_MAJOR_MINOR} \ libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; \ fi - if test -f ../../src/objfw.dll; then \ - ${LN_S} ../../src/objfw.dll objfw.dll; \ + if test -f ../../src/objfw${OBJFW_LIB_MAJOR}.dll; then \ + ${LN_S} ../../src/objfw${OBJFW_LIB_MAJOR}.dll \ + objfw${OBJFW_LIB_MAJOR}.dll; \ fi if test -f ../../src/libobjfw.dylib; then \ ${LN_S} ../../src/libobjfw.dylib \ libobjfw.${OBJFW_LIB_MAJOR}.dylib; \ fi @@ -36,12 +38,13 @@ ${LN_S} ../../src/runtime/libobjfwrt.so \ libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; \ elif test -f ../../src/runtime/libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; then \ ${LN_S} ../../src/runtime/libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR} libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; \ fi - if test -f ../../src/runtime/objfwrt.dll; then \ - ${LN_S} ../../src/runtime/objfwrt.dll objfwrt.dll; \ + if test -f ../../src/runtime/objfwrt${OBJFWRT_LIB_MAJOR}.dll; then \ + ${LN_S} ../../src/runtime/objfwrt${OBJFWRT_LIB_MAJOR}.dll \ + objfwrt${OBJFWRT_LIB_MAJOR}.dll; \ fi if test -f ../../src/runtime/libobjfwrt.dylib; then \ ${LN_S} ../../src/runtime/libobjfwrt.dylib \ libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib; \ fi @@ -54,17 +57,19 @@ DYLD_LIBRARY_PATH=.$${DYLD_LIBRARY_PATH+:}$$DYLD_LIBRARY_PATH \ LIBRARY_PATH=.$${LIBRARY_PATH+:}$$LIBRARY_PATH \ ASAN_OPTIONS=allocator_may_return_null=1 \ ${WRAPPER} ./${PROG_NOINST}; EXIT=$$?; \ rm -f libobjfw.so.${OBJFW_LIB_MAJOR}; \ - rm -f objfw.so.${OBJFW_LIB_MAJOR_MINOR} objfw.dll; \ + rm -f libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; \ + rm -f objfw${OBJFW_LIB_MAJOR}.dll; \ rm -f libobjfw.${OBJFW_LIB_MAJOR}.dylib; \ rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR}; \ - rm -f objfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR} objfwrt.dll; \ + rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; \ + rm -f objfwrt${OBJFWRT_LIB_MAJOR}.dll; \ rm -f libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib; \ exit $$EXIT include ../../buildsys.mk CPPFLAGS += -I../../src -I../../src/exceptions -I../../src/runtime -I../.. LIBS := -L../../src -lobjfw -L../../src/runtime ${RUNTIME_LIBS} ${LIBS} LD = ${OBJC} Index: generators/unicode/Makefile ================================================================== --- generators/unicode/Makefile +++ generators/unicode/Makefile @@ -5,25 +5,27 @@ .PHONY: run run: all rm -f libobjfw.so.${OBJFW_LIB_MAJOR} rm -f libobjfw.so.${OBJFW_LIB_MAJOR_MINOR} - rm -f objfw.dll libobjfw.${OBJFW_LIB_MAJOR}.dylib + rm -f objfw${OBJFW_LIB_MAJOR}.dll libobjfw.${OBJFW_LIB_MAJOR}.dylib rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR} rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR} - rm -f objfwrt.dll libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib + rm -f objfwrt${OBJFWRT_LIB_MAJOR}.dll + rm -f libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib rm -f ${OBJFWRT_AMIGA_LIB} if test -f ../../src/libobjfw.so; then \ ${LN_S} ../../src/libobjfw.so libobjfw.so.${OBJFW_LIB_MAJOR}; \ ${LN_S} ../../src/libobjfw.so \ libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; \ elif test -f ../../src/libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; then \ ${LN_S} ../../src/libobjfw.so.${OBJFW_LIB_MAJOR_MINOR} \ libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; \ fi - if test -f ../../src/objfw.dll; then \ - ${LN_S} ../../src/objfw.dll objfw.dll; \ + if test -f ../../src/objfw${OBJFW_LIB_MAJOR}.dll; then \ + ${LN_S} ../../src/objfw${OBJFW_LIB_MAJOR}.dll \ + objfw${OBJFW_LIB_MAJOR}.dll; \ fi if test -f ../../src/libobjfw.dylib; then \ ${LN_S} ../../src/libobjfw.dylib \ libobjfw.${OBJFW_LIB_MAJOR}.dylib; \ fi @@ -33,12 +35,13 @@ ${LN_S} ../../src/runtime/libobjfwrt.so \ libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; \ elif test -f ../../src/runtime/libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; then \ ${LN_S} ../../src/runtime/libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR} libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; \ fi - if test -f ../../src/runtime/objfwrt.dll; then \ - ${LN_S} ../../src/runtime/objfwrt.dll objfwrt.dll; \ + if test -f ../../src/runtime/objfwrt${OBJFWRT_LIB_MAJOR}.dll; then \ + ${LN_S} ../../src/runtime/objfwrt${OBJFWRT_LIB_MAJOR}.dll \ + objfwrt${OBJFWRT_LIB_MAJOR}.dll; \ fi if test -f ../../src/runtime/libobjfwrt.dylib; then \ ${LN_S} ../../src/runtime/libobjfwrt.dylib \ libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib; \ fi @@ -51,17 +54,19 @@ DYLD_LIBRARY_PATH=.$${DYLD_LIBRARY_PATH+:}$$DYLD_LIBRARY_PATH \ LIBRARY_PATH=.$${LIBRARY_PATH+:}$$LIBRARY_PATH \ ASAN_OPTIONS=allocator_may_return_null=1 \ ${WRAPPER} ./${PROG_NOINST}; EXIT=$$?; \ rm -f libobjfw.so.${OBJFW_LIB_MAJOR}; \ - rm -f objfw.so.${OBJFW_LIB_MAJOR_MINOR} objfw.dll; \ + rm -f libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; \ + rm -f objfw${OBJFW_LIB_MAJOR}.dll; \ rm -f libobjfw.${OBJFW_LIB_MAJOR}.dylib; \ rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR}; \ - rm -f objfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR} objfwrt.dll; \ + rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; \ + rm -f objfwrt${OBJFWRT_LIB_MAJOR}.dll; \ rm -f libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib; \ exit $$EXIT include ../../buildsys.mk CPPFLAGS += -I../../src -I../../src/exceptions -I../../src/runtime -I../.. LIBS := -L../../src -lobjfw -L../../src/runtime ${RUNTIME_LIBS} ${LIBS} LD = ${OBJC} ADDED objfw.spec Index: objfw.spec ================================================================== --- objfw.spec +++ objfw.spec @@ -0,0 +1,363 @@ +Name: objfw +Version: 1.0 +Release: 1%{?dist} +Summary: Portable, lightweight framework for the Objective-C language + +License: QPL or GPLv2 or GPLv3 +URL: https://objfw.nil.im +Source0: objfw-%{version}.tar.gz + +BuildRequires: clang +BuildRequires: make +Requires: libobjfw%{_isa} = %{version}-%{release} +Requires: libobjfw-devel = %{version}-%{release} +Requires: libobjfwrt%{_isa} = %{version}-%{release} +Requires: libobjfwrt-devel = %{version}-%{release} +Requires: ofarc%{_isa} = %{version}-%{release} +Requires: ofdns%{_isa} = %{version}-%{release} +Requires: ofhash%{_isa} = %{version}-%{release} +Requires: ofhttp%{_isa} = %{version}-%{release} + +%description +ObjFW is a portable, lightweight framework for the Objective-C language. It +enables you to write an application in Objective-C that will run on any +platform supported by ObjFW without having to worry about differences between +operating systems or various frameworks you would otherwise need if you want to +be portable. + +It supports all modern Objective-C features when using Clang, but is also +compatible with GCC ≥ 4.6 to allow maximum portability. + +ObjFW also comes with its own lightweight and extremely fast Objective-C +runtime, which in real world use cases was found to be significantly faster +than both GNU's and Apple's runtime. + +%package -n libobjfw +Summary: ObjFW library +Requires: libobjfwrt%{_isa} = %{version}-%{release} + +%description -n libobjfw +The libobjfw package contains the library needed by programs using ObjFW. + +%package -n libobjfw-devel +Summary: Header files and tools for libobjfw +Requires: libobjfw%{_isa} = %{version}-%{release} +Requires: libobjfwrt-devel = %{version}-%{release} + +%description -n libobjfw-devel +The libobjfw-devel package contains the header files and tools to develop +programs using ObjFW. + +%package -n libobjfwrt +Summary: ObjFW Objective-C runtime library + +%description -n libobjfwrt +The libobjfwrt package contains ObjFW's Objective-C runtime library. + +%package -n libobjfwrt-devel +Summary: Header files for libobjfwrt + +%description -n libobjfwrt-devel +The libobjfwrt-devel package contains header files for ObjFW's Objective-C +runtime library. + +%package -n ofarc +Summary: Utility for handling ZIP, Tar and LHA archives +Requires: libobjfw%{_isa} = %{version}-%{release} +Requires: libobjfwrt%{_isa} = %{version}-%{release} + +%description -n ofarc +ofarc is a multi-format archive utility that allows creating, listing, +extracting and modifying ZIP, Tar and LHA archives using ObjFW's classes for +various archive types. + +%package -n ofdns +Summary: Utility for performing DNS requests on the command line +Requires: libobjfw%{_isa} = %{version}-%{release} +Requires: libobjfwrt%{_isa} = %{version}-%{release} + +%description -n ofdns +ofdns is an utility for performing DNS requests on the command line using +ObjFW's DNS resolver. + +%package -n ofhash +Summary: Utility to hash files with various cryptographic hash functions +Requires: libobjfw%{_isa} = %{version}-%{release} +Requires: libobjfwrt%{_isa} = %{version}-%{release} + +%description -n ofhash +ofhash is an utility to hash files with various cryptographic hash functions +(even using different algorithms at once) using ObjFW's classes for various +cryptographic hashes. + +%package -n ofhttp +Summary: Command line downloader for HTTP(S) +Requires: libobjfw%{_isa} = %{version}-%{release} +Requires: libobjfwrt%{_isa} = %{version}-%{release} + +%description -n ofhttp +ofhttp is a command line downloader for HTTP and HTTPS (via ObjOpenSSL) using +ObjFW's OFHTTPClient class. It supports all features one would expect from a +modern command line downloader such as resuming of downloads, using a SOCKS5 +proxy, a modern terminal-based UI, etc. + +%prep +%autosetup + +%build +%configure --disable-rpath +%make_build + +%install +%make_install + +%files + +%files -n libobjfw +%{_libdir}/libobjfw.so.1 +%{_libdir}/libobjfw.so.1.0.0 + +%files -n libobjfw-devel +%{_libdir}/libobjfw.so +%{_includedir}/ObjFW/OFASPrintF.h +%{_includedir}/ObjFW/OFAcceptFailedException.h +%{_includedir}/ObjFW/OFAllocFailedException.h +%{_includedir}/ObjFW/OFAlreadyConnectedException.h +%{_includedir}/ObjFW/OFApplication.h +%{_includedir}/ObjFW/OFArray.h +%{_includedir}/ObjFW/OFAtomic.h +%{_includedir}/ObjFW/OFBase64.h +%{_includedir}/ObjFW/OFBindFailedException.h +%{_includedir}/ObjFW/OFBlock.h +%{_includedir}/ObjFW/OFCRC16.h +%{_includedir}/ObjFW/OFCRC32.h +%{_includedir}/ObjFW/OFChangeCurrentDirectoryPathFailedException.h +%{_includedir}/ObjFW/OFCharacterSet.h +%{_includedir}/ObjFW/OFChecksumMismatchException.h +%{_includedir}/ObjFW/OFCollection.h +%{_includedir}/ObjFW/OFColor.h +%{_includedir}/ObjFW/OFCondition.h +%{_includedir}/ObjFW/OFConditionBroadcastFailedException.h +%{_includedir}/ObjFW/OFConditionSignalFailedException.h +%{_includedir}/ObjFW/OFConditionStillWaitingException.h +%{_includedir}/ObjFW/OFConditionWaitFailedException.h +%{_includedir}/ObjFW/OFConnectionFailedException.h +%{_includedir}/ObjFW/OFConstantString.h +%{_includedir}/ObjFW/OFCopyItemFailedException.h +%{_includedir}/ObjFW/OFCountedSet.h +%{_includedir}/ObjFW/OFCreateDirectoryFailedException.h +%{_includedir}/ObjFW/OFCreateSymbolicLinkFailedException.h +%{_includedir}/ObjFW/OFCryptographicHash.h +%{_includedir}/ObjFW/OFDNSQuery.h +%{_includedir}/ObjFW/OFDNSQueryFailedException.h +%{_includedir}/ObjFW/OFDNSResolver.h +%{_includedir}/ObjFW/OFDNSResourceRecord.h +%{_includedir}/ObjFW/OFDNSResponse.h +%{_includedir}/ObjFW/OFData+CryptographicHashing.h +%{_includedir}/ObjFW/OFData+MessagePackParsing.h +%{_includedir}/ObjFW/OFData.h +%{_includedir}/ObjFW/OFDatagramSocket.h +%{_includedir}/ObjFW/OFDate.h +%{_includedir}/ObjFW/OFDictionary.h +%{_includedir}/ObjFW/OFEnumerationMutationException.h +%{_includedir}/ObjFW/OFEnumerator.h +%{_includedir}/ObjFW/OFException.h +%{_includedir}/ObjFW/OFFile.h +%{_includedir}/ObjFW/OFFileManager.h +%{_includedir}/ObjFW/OFGZIPStream.h +%{_includedir}/ObjFW/OFGetCurrentDirectoryPathFailedException.h +%{_includedir}/ObjFW/OFGetOptionFailedException.h +%{_includedir}/ObjFW/OFHMAC.h +%{_includedir}/ObjFW/OFHTTPClient.h +%{_includedir}/ObjFW/OFHTTPCookie.h +%{_includedir}/ObjFW/OFHTTPCookieManager.h +%{_includedir}/ObjFW/OFHTTPRequest.h +%{_includedir}/ObjFW/OFHTTPRequestFailedException.h +%{_includedir}/ObjFW/OFHTTPResponse.h +%{_includedir}/ObjFW/OFHTTPServer.h +%{_includedir}/ObjFW/OFHashAlreadyCalculatedException.h +%{_includedir}/ObjFW/OFHuffmanTree.h +%{_includedir}/ObjFW/OFINICategory.h +%{_includedir}/ObjFW/OFINIFile.h +%{_includedir}/ObjFW/OFIPXSocket.h +%{_includedir}/ObjFW/OFInflate64Stream.h +%{_includedir}/ObjFW/OFInflateStream.h +%{_includedir}/ObjFW/OFInitializationFailedException.h +%{_includedir}/ObjFW/OFInvalidArgumentException.h +%{_includedir}/ObjFW/OFInvalidEncodingException.h +%{_includedir}/ObjFW/OFInvalidFormatException.h +%{_includedir}/ObjFW/OFInvalidJSONException.h +%{_includedir}/ObjFW/OFInvalidServerReplyException.h +%{_includedir}/ObjFW/OFInvocation.h +%{_includedir}/ObjFW/OFJSONRepresentation.h +%{_includedir}/ObjFW/OFKernelEventObserver.h +%{_includedir}/ObjFW/OFKeyValueCoding.h +%{_includedir}/ObjFW/OFLHAArchive.h +%{_includedir}/ObjFW/OFLHAArchiveEntry.h +%{_includedir}/ObjFW/OFLinkFailedException.h +%{_includedir}/ObjFW/OFList.h +%{_includedir}/ObjFW/OFListenFailedException.h +%{_includedir}/ObjFW/OFLoadPluginFailedException.h +%{_includedir}/ObjFW/OFLocale.h +%{_includedir}/ObjFW/OFLockFailedException.h +%{_includedir}/ObjFW/OFLocking.h +%{_includedir}/ObjFW/OFMD5Hash.h +%{_includedir}/ObjFW/OFMalformedXMLException.h +%{_includedir}/ObjFW/OFMapTable.h +%{_includedir}/ObjFW/OFMemoryNotPartOfObjectException.h +%{_includedir}/ObjFW/OFMessagePackExtension.h +%{_includedir}/ObjFW/OFMessagePackRepresentation.h +%{_includedir}/ObjFW/OFMethodSignature.h +%{_includedir}/ObjFW/OFMoveItemFailedException.h +%{_includedir}/ObjFW/OFMutableArray.h +%{_includedir}/ObjFW/OFMutableData.h +%{_includedir}/ObjFW/OFMutableDictionary.h +%{_includedir}/ObjFW/OFMutableLHAArchiveEntry.h +%{_includedir}/ObjFW/OFMutablePair.h +%{_includedir}/ObjFW/OFMutableSet.h +%{_includedir}/ObjFW/OFMutableString.h +%{_includedir}/ObjFW/OFMutableTarArchiveEntry.h +%{_includedir}/ObjFW/OFMutableTriple.h +%{_includedir}/ObjFW/OFMutableURL.h +%{_includedir}/ObjFW/OFMutableZIPArchiveEntry.h +%{_includedir}/ObjFW/OFMutex.h +%{_includedir}/ObjFW/OFNotImplementedException.h +%{_includedir}/ObjFW/OFNotOpenException.h +%{_includedir}/ObjFW/OFNull.h +%{_includedir}/ObjFW/OFNumber.h +%{_includedir}/ObjFW/OFObject+KeyValueCoding.h +%{_includedir}/ObjFW/OFObject+Serialization.h +%{_includedir}/ObjFW/OFObject.h +%{_includedir}/ObjFW/OFObserveFailedException.h +%{_includedir}/ObjFW/OFOnce.h +%{_includedir}/ObjFW/OFOpenItemFailedException.h +%{_includedir}/ObjFW/OFOptionsParser.h +%{_includedir}/ObjFW/OFOutOfMemoryException.h +%{_includedir}/ObjFW/OFOutOfRangeException.h +%{_includedir}/ObjFW/OFPBKDF2.h +%{_includedir}/ObjFW/OFPair.h +%{_includedir}/ObjFW/OFPlainCondition.h +%{_includedir}/ObjFW/OFPlainMutex.h +%{_includedir}/ObjFW/OFPlainThread.h +%{_includedir}/ObjFW/OFPlugin.h +%{_includedir}/ObjFW/OFRIPEMD160Hash.h +%{_includedir}/ObjFW/OFReadFailedException.h +%{_includedir}/ObjFW/OFReadOrWriteFailedException.h +%{_includedir}/ObjFW/OFRecursiveMutex.h +%{_includedir}/ObjFW/OFRemoveItemFailedException.h +%{_includedir}/ObjFW/OFResolveHostFailedException.h +%{_includedir}/ObjFW/OFRetrieveItemAttributesFailedException.h +%{_includedir}/ObjFW/OFRunLoop.h +%{_includedir}/ObjFW/OFSHA1Hash.h +%{_includedir}/ObjFW/OFSHA224Hash.h +%{_includedir}/ObjFW/OFSHA224Or256Hash.h +%{_includedir}/ObjFW/OFSHA256Hash.h +%{_includedir}/ObjFW/OFSHA384Hash.h +%{_includedir}/ObjFW/OFSHA384Or512Hash.h +%{_includedir}/ObjFW/OFSHA512Hash.h +%{_includedir}/ObjFW/OFSPXSocket.h +%{_includedir}/ObjFW/OFSPXStreamSocket.h +%{_includedir}/ObjFW/OFScrypt.h +%{_includedir}/ObjFW/OFSecureData.h +%{_includedir}/ObjFW/OFSeekFailedException.h +%{_includedir}/ObjFW/OFSeekableStream.h +%{_includedir}/ObjFW/OFSequencedPacketSocket.h +%{_includedir}/ObjFW/OFSerialization.h +%{_includedir}/ObjFW/OFSet.h +%{_includedir}/ObjFW/OFSetItemAttributesFailedException.h +%{_includedir}/ObjFW/OFSetOptionFailedException.h +%{_includedir}/ObjFW/OFSettings.h +%{_includedir}/ObjFW/OFSocket.h +%{_includedir}/ObjFW/OFSortedList.h +%{_includedir}/ObjFW/OFStdIOStream.h +%{_includedir}/ObjFW/OFStillLockedException.h +%{_includedir}/ObjFW/OFStrPTime.h +%{_includedir}/ObjFW/OFStream.h +%{_includedir}/ObjFW/OFStreamSocket.h +%{_includedir}/ObjFW/OFString+CryptographicHashing.h +%{_includedir}/ObjFW/OFString+JSONParsing.h +%{_includedir}/ObjFW/OFString+PathAdditions.h +%{_includedir}/ObjFW/OFString+PropertyListParsing.h +%{_includedir}/ObjFW/OFString+Serialization.h +%{_includedir}/ObjFW/OFString+URLEncoding.h +%{_includedir}/ObjFW/OFString+XMLEscaping.h +%{_includedir}/ObjFW/OFString+XMLUnescaping.h +%{_includedir}/ObjFW/OFString.h +%{_includedir}/ObjFW/OFSystemInfo.h +%{_includedir}/ObjFW/OFTCPSocket.h +%{_includedir}/ObjFW/OFTLSKey.h +%{_includedir}/ObjFW/OFTLSSocket.h +%{_includedir}/ObjFW/OFTarArchive.h +%{_includedir}/ObjFW/OFTarArchiveEntry.h +%{_includedir}/ObjFW/OFThread.h +%{_includedir}/ObjFW/OFThreadJoinFailedException.h +%{_includedir}/ObjFW/OFThreadPool.h +%{_includedir}/ObjFW/OFThreadStartFailedException.h +%{_includedir}/ObjFW/OFThreadStillRunningException.h +%{_includedir}/ObjFW/OFTimer.h +%{_includedir}/ObjFW/OFTriple.h +%{_includedir}/ObjFW/OFTruncatedDataException.h +%{_includedir}/ObjFW/OFUDPSocket.h +%{_includedir}/ObjFW/OFURL.h +%{_includedir}/ObjFW/OFURLHandler.h +%{_includedir}/ObjFW/OFUnboundNamespaceException.h +%{_includedir}/ObjFW/OFUnboundPrefixException.h +%{_includedir}/ObjFW/OFUndefinedKeyException.h +%{_includedir}/ObjFW/OFUnknownXMLEntityException.h +%{_includedir}/ObjFW/OFUnlockFailedException.h +%{_includedir}/ObjFW/OFUnsupportedProtocolException.h +%{_includedir}/ObjFW/OFUnsupportedVersionException.h +%{_includedir}/ObjFW/OFValue.h +%{_includedir}/ObjFW/OFWriteFailedException.h +%{_includedir}/ObjFW/OFXMLAttribute.h +%{_includedir}/ObjFW/OFXMLCDATA.h +%{_includedir}/ObjFW/OFXMLCharacters.h +%{_includedir}/ObjFW/OFXMLComment.h +%{_includedir}/ObjFW/OFXMLElement+Serialization.h +%{_includedir}/ObjFW/OFXMLElement.h +%{_includedir}/ObjFW/OFXMLElementBuilder.h +%{_includedir}/ObjFW/OFXMLNode.h +%{_includedir}/ObjFW/OFXMLParser.h +%{_includedir}/ObjFW/OFXMLProcessingInstruction.h +%{_includedir}/ObjFW/OFZIPArchive.h +%{_includedir}/ObjFW/OFZIPArchiveEntry.h +%{_includedir}/ObjFW/ObjFW.h +%{_includedir}/ObjFW/macros.h +%{_includedir}/ObjFW/objfw-defs.h +%{_includedir}/ObjFW/platform.h +%{_includedir}/ObjFW/platform/GCC4.7/OFAtomic.h +%{_includedir}/ObjFW/platform/GCC4/OFAtomic.h +%{_includedir}/ObjFW/platform/PowerPC/OFAtomic.h +%{_includedir}/ObjFW/platform/macOS/OFAtomic.h +%{_includedir}/ObjFW/platform/x86/OFAtomic.h +%{_bindir}/objfw-compile +%{_bindir}/objfw-config +%{_bindir}/objfw-new + +%files -n libobjfwrt +%{_libdir}/libobjfwrt.so.1 +%{_libdir}/libobjfwrt.so.1.0.0 + +%files -n libobjfwrt-devel +%{_libdir}/libobjfwrt.so +%{_includedir}/ObjFWRT/ObjFWRT.h + +%files -n ofarc +%{_bindir}/ofarc +%{_datadir}/ofarc/lang/de.json +%{_datadir}/ofarc/lang/languages.json + +%files -n ofdns +%{_bindir}/ofdns +%{_datadir}/ofdns/lang/de.json +%{_datadir}/ofdns/lang/languages.json + +%files -n ofhash +%{_bindir}/ofhash +%{_datadir}/ofhash/lang/de.json +%{_datadir}/ofhash/lang/languages.json + +%files -n ofhttp +%{_bindir}/ofhttp +%{_datadir}/ofhttp/lang/de.json +%{_datadir}/ofhttp/lang/languages.json Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -151,16 +151,15 @@ OFThreadPool.m SRCS_WINDOWS = OFWin32ConsoleStdIOStream.m \ OFWindowsRegistryKey.m INCLUDES_ATOMIC = OFAtomic.h \ - OFAtomic_builtins.h \ - OFAtomic_no_threads.h \ - OFAtomic_osatomic.h \ - OFAtomic_powerpc.h \ - OFAtomic_sync_builtins.h \ - OFAtomic_x86.h + platform/GCC4/OFAtomic.h \ + platform/GCC4.7/OFAtomic.h \ + platform/PowerPC/OFAtomic.h \ + platform/macOS/OFAtomic.h \ + platform/x86/OFAtomic.h INCLUDES := ${SRCS:.m=.h} \ OFCollection.h \ OFCryptographicHash.h \ OFJSONRepresentation.h \ OFKernelEventObserver.h \ Index: src/OFASPrintF.m ================================================================== --- src/OFASPrintF.m +++ src/OFASPrintF.m @@ -51,11 +51,11 @@ */ # define asprintf asprintf_ # define vasprintf vasprintf_ #endif -struct context { +struct Context { const char *format; size_t formatLen; char subformat[maxSubformatLen + 1]; size_t subformatLen; va_list arguments; @@ -146,11 +146,11 @@ return ret; } #endif static bool -appendString(struct context *ctx, const char *append, size_t appendLen) +appendString(struct Context *ctx, const char *append, size_t appendLen) { char *newBuf; if (appendLen == 0) return true; @@ -166,11 +166,11 @@ return true; } static bool -appendSubformat(struct context *ctx, const char *subformat, +appendSubformat(struct Context *ctx, const char *subformat, size_t subformatLen) { if (ctx->subformatLen + subformatLen > maxSubformatLen) return false; @@ -180,11 +180,11 @@ return true; } static bool -stringState(struct context *ctx) +stringState(struct Context *ctx) { if (ctx->format[ctx->i] == '%') { if (ctx->i > 0) if (!appendString(ctx, ctx->format + ctx->last, ctx->i - ctx->last)) @@ -199,11 +199,11 @@ return true; } static bool -formatFlagsState(struct context *ctx) +formatFlagsState(struct Context *ctx) { switch (ctx->format[ctx->i]) { case '-': case '+': case ' ': @@ -226,11 +226,11 @@ return true; } static bool -formatFieldWidthState(struct context *ctx) +formatFieldWidthState(struct Context *ctx) { if ((ctx->format[ctx->i] >= '0' && ctx->format[ctx->i] <= '9') || ctx->format[ctx->i] == '*' || ctx->format[ctx->i] == '.') { if (!appendSubformat(ctx, ctx->format + ctx->i, 1)) return false; @@ -241,11 +241,11 @@ return true; } static bool -formatLengthModifierState(struct context *ctx) +formatLengthModifierState(struct Context *ctx) { /* Only one allowed */ switch (ctx->format[ctx->i]) { case 'h': /* and also hh */ if (ctx->formatLen > ctx->i + 1 && @@ -371,11 +371,11 @@ ctx->state = stateFormatConversionSpecifier; return true; } static bool -formatConversionSpecifierState(struct context *ctx) +formatConversionSpecifierState(struct Context *ctx) { char *tmp = NULL; int tmpLen = 0; #ifndef HAVE_ASPRINTF_L OFString *point; @@ -729,11 +729,11 @@ ctx->state = stateString; return true; } -static bool (*states[])(struct context *) = { +static bool (*states[])(struct Context *) = { stringState, formatFlagsState, formatFieldWidthState, formatLengthModifierState, formatConversionSpecifierState @@ -740,11 +740,11 @@ }; int OFVASPrintF(char **string, const char *format, va_list arguments) { - struct context ctx; + struct Context ctx; ctx.format = format; ctx.formatLen = strlen(format); memset(ctx.subformat, 0, maxSubformatLen + 1); ctx.subformatLen = 0; Index: src/OFArray.m ================================================================== --- src/OFArray.m +++ src/OFArray.m @@ -237,22 +237,25 @@ - (id const *)objects { size_t count = self.count; id *buffer = OFAllocMemory(count, sizeof(id)); + id const *ret; @try { [self getObjects: buffer inRange: OFRangeMake(0, count)]; - return [[OFData dataWithItemsNoCopy: buffer - count: count - itemSize: sizeof(id) - freeWhenDone: true] items]; + ret = [[OFData dataWithItemsNoCopy: buffer + count: count + itemSize: sizeof(id) + freeWhenDone: true] items]; } @catch (id e) { OFFreeMemory(buffer); @throw e; } + + return ret; } - (id)copy { return [self retain]; Index: src/OFAtomic.h ================================================================== --- src/OFAtomic.h +++ src/OFAtomic.h @@ -20,20 +20,166 @@ #ifndef OF_HAVE_ATOMIC_OPS # error No atomic operations available! #endif #if !defined(OF_HAVE_THREADS) -# import "OFAtomic_no_threads.h" +static OF_INLINE int +OFAtomicIntAdd(volatile int *_Nonnull p, int i) +{ + return (*p += i); +} + +static OF_INLINE int32_t +OFAtomicInt32Add(volatile int32_t *_Nonnull p, int32_t i) +{ + return (*p += i); +} + +static OF_INLINE void *_Nullable +OFAtomicPointerAdd(void *volatile _Nullable *_Nonnull p, intptr_t i) +{ + return (*(char *volatile *)p += i); +} + +static OF_INLINE int +OFAtomicIntSubtract(volatile int *_Nonnull p, int i) +{ + return (*p -= i); +} + +static OF_INLINE int32_t +OFAtomicInt32Subtract(volatile int32_t *_Nonnull p, int32_t i) +{ + return (*p -= i); +} + +static OF_INLINE void *_Nullable +OFAtomicPointerSubtract(void *volatile _Nullable *_Nonnull p, intptr_t i) +{ + return (*(char *volatile *)p -= i); +} + +static OF_INLINE int +OFAtomicIntIncrease(volatile int *_Nonnull p) +{ + return ++*p; +} + +static OF_INLINE int32_t +OFAtomicInt32Increase(volatile int32_t *_Nonnull p) +{ + return ++*p; +} + +static OF_INLINE int +OFAtomicIntDecrease(volatile int *_Nonnull p) +{ + return --*p; +} + +static OF_INLINE int32_t +OFAtomicInt32Decrease(volatile int32_t *_Nonnull p) +{ + return --*p; +} + +static OF_INLINE unsigned int +OFAtomicIntOr(volatile unsigned int *_Nonnull p, unsigned int i) +{ + return (*p |= i); +} + +static OF_INLINE uint32_t +OFAtomicInt32Or(volatile uint32_t *_Nonnull p, uint32_t i) +{ + return (*p |= i); +} + +static OF_INLINE unsigned int +OFAtomicIntAnd(volatile unsigned int *_Nonnull p, unsigned int i) +{ + return (*p &= i); +} + +static OF_INLINE uint32_t +OFAtomicInt32And(volatile uint32_t *_Nonnull p, uint32_t i) +{ + return (*p &= i); +} + +static OF_INLINE unsigned int +OFAtomicIntXor(volatile unsigned int *_Nonnull p, unsigned int i) +{ + return (*p ^= i); +} + +static OF_INLINE uint32_t +OFAtomicInt32Xor(volatile uint32_t *_Nonnull p, uint32_t i) +{ + return (*p ^= i); +} + +static OF_INLINE bool +OFAtomicIntCompareAndSwap(volatile int *_Nonnull p, int o, int n) +{ + if (*p == o) { + *p = n; + return true; + } + + return false; +} + +static OF_INLINE bool +OFAtomicInt32CompareAndSwap(volatile int32_t *_Nonnull p, int32_t o, int32_t n) +{ + if (*p == o) { + *p = n; + return true; + } + + return false; +} + +static OF_INLINE bool +OFAtomicPointerCompareAndSwap(void *volatile _Nullable *_Nonnull p, + void *_Nullable o, void *_Nullable n) +{ + if (*p == o) { + *p = n; + return true; + } + + return false; +} + +static OF_INLINE void +OFMemoryBarrier(void) +{ + /* nop */ +} + +static OF_INLINE void +OFAcquireMemoryBarrier(void) +{ + /* nop */ +} + +static OF_INLINE void +OFReleaseMemoryBarrier(void) +{ + /* nop */ +} #elif (defined(OF_X86_64) || defined(OF_X86)) && defined(__GNUC__) -# import "OFAtomic_x86.h" +# import "platform/x86/OFAtomic.h" #elif defined(OF_POWERPC) && defined(__GNUC__) && !defined(__APPLE_CC__) && \ !defined(OF_AIX) -# import "OFAtomic_powerpc.h" +# import "platform/PowerPC/OFAtomic.h" #elif defined(OF_HAVE_ATOMIC_BUILTINS) -# import "OFAtomic_builtins.h" +# import "platform/GCC4.7/OFAtomic.h" #elif defined(OF_HAVE_SYNC_BUILTINS) -# import "OFAtomic_sync_builtins.h" +# import "platform/GCC4/OFAtomic.h" #elif defined(OF_HAVE_OSATOMIC) -# import "OFAtomic_osatomic.h" +# import "platform/macOS/OFAtomic.h" #else # error No atomic operations available! #endif DELETED src/OFAtomic_builtins.h Index: src/OFAtomic_builtins.h ================================================================== --- src/OFAtomic_builtins.h +++ src/OFAtomic_builtins.h @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -static OF_INLINE int -OFAtomicIntAdd(volatile int *_Nonnull p, int i) -{ - return __atomic_add_fetch(p, i, __ATOMIC_RELAXED); -} - -static OF_INLINE int32_t -OFAtomicInt32Add(volatile int32_t *_Nonnull p, int32_t i) -{ - return __atomic_add_fetch(p, i, __ATOMIC_RELAXED); -} - -static OF_INLINE void *_Nullable -OFAtomicPointerAdd(void *volatile _Nullable *_Nonnull p, intptr_t i) -{ - return __atomic_add_fetch(p, i, __ATOMIC_RELAXED); -} - -static OF_INLINE int -OFAtomicIntSubtract(volatile int *_Nonnull p, int i) -{ - return __atomic_sub_fetch(p, i, __ATOMIC_RELAXED); -} - -static OF_INLINE int32_t -OFAtomicInt32Subtract(volatile int32_t *_Nonnull p, int32_t i) -{ - return __atomic_sub_fetch(p, i, __ATOMIC_RELAXED); -} - -static OF_INLINE void *_Nullable -OFAtomicPointerSubtract(void *volatile _Nullable *_Nonnull p, intptr_t i) -{ - return __atomic_sub_fetch(p, i, __ATOMIC_RELAXED); -} - -static OF_INLINE int -OFAtomicIntIncrease(volatile int *_Nonnull p) -{ - return __atomic_add_fetch(p, 1, __ATOMIC_RELAXED); -} - -static OF_INLINE int32_t -OFAtomicInt32Increase(volatile int32_t *_Nonnull p) -{ - return __atomic_add_fetch(p, 1, __ATOMIC_RELAXED); -} - -static OF_INLINE int -OFAtomicIntDecrease(volatile int *_Nonnull p) -{ - return __atomic_sub_fetch(p, 1, __ATOMIC_RELAXED); -} - -static OF_INLINE int32_t -OFAtomicInt32Decrease(volatile int32_t *_Nonnull p) -{ - return __atomic_sub_fetch(p, 1, __ATOMIC_RELAXED); -} - -static OF_INLINE unsigned int -OFAtomicIntOr(volatile unsigned int *_Nonnull p, unsigned int i) -{ - return __atomic_or_fetch(p, i, __ATOMIC_RELAXED); -} - -static OF_INLINE uint32_t -OFAtomicInt32Or(volatile uint32_t *_Nonnull p, uint32_t i) -{ - return __atomic_or_fetch(p, i, __ATOMIC_RELAXED); -} - -static OF_INLINE unsigned int -OFAtomicIntAnd(volatile unsigned int *_Nonnull p, unsigned int i) -{ - return __atomic_and_fetch(p, i, __ATOMIC_RELAXED); -} - -static OF_INLINE uint32_t -OFAtomicInt32And(volatile uint32_t *_Nonnull p, uint32_t i) -{ - return __atomic_and_fetch(p, i, __ATOMIC_RELAXED); -} - -static OF_INLINE unsigned int -OFAtomicIntXor(volatile unsigned int *_Nonnull p, unsigned int i) -{ - return __atomic_xor_fetch(p, i, __ATOMIC_RELAXED); -} - -static OF_INLINE uint32_t -OFAtomicInt32Xor(volatile uint32_t *_Nonnull p, uint32_t i) -{ - return __atomic_xor_fetch(p, i, __ATOMIC_RELAXED); -} - -static OF_INLINE bool -OFAtomicIntCompareAndSwap(volatile int *_Nonnull p, int o, int n) -{ - return __atomic_compare_exchange(p, &o, &n, false, - __ATOMIC_RELAXED, __ATOMIC_RELAXED); -} - -static OF_INLINE bool -OFAtomicInt32CompareAndSwap(volatile int32_t *_Nonnull p, int32_t o, int32_t n) -{ - return __atomic_compare_exchange(p, &o, &n, false, - __ATOMIC_RELAXED, __ATOMIC_RELAXED); -} - -static OF_INLINE bool -OFAtomicPointerCompareAndSwap(void *volatile _Nullable *_Nonnull p, - void *_Nullable o, void *_Nullable n) -{ - return __atomic_compare_exchange(p, &o, &n, false, - __ATOMIC_RELAXED, __ATOMIC_RELAXED); -} - -static OF_INLINE void -OFMemoryBarrier(void) -{ - __atomic_thread_fence(__ATOMIC_SEQ_CST); -} - -static OF_INLINE void -OFAcquireMemoryBarrier(void) -{ - __atomic_thread_fence(__ATOMIC_ACQUIRE); -} - -static OF_INLINE void -OFReleaseMemoryBarrier(void) -{ - __atomic_thread_fence(__ATOMIC_RELEASE); -} DELETED src/OFAtomic_no_threads.h Index: src/OFAtomic_no_threads.h ================================================================== --- src/OFAtomic_no_threads.h +++ src/OFAtomic_no_threads.h @@ -1,162 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -static OF_INLINE int -OFAtomicIntAdd(volatile int *_Nonnull p, int i) -{ - return (*p += i); -} - -static OF_INLINE int32_t -OFAtomicInt32Add(volatile int32_t *_Nonnull p, int32_t i) -{ - return (*p += i); -} - -static OF_INLINE void *_Nullable -OFAtomicPointerAdd(void *volatile _Nullable *_Nonnull p, intptr_t i) -{ - return (*(char *volatile *)p += i); -} - -static OF_INLINE int -OFAtomicIntSubtract(volatile int *_Nonnull p, int i) -{ - return (*p -= i); -} - -static OF_INLINE int32_t -OFAtomicInt32Subtract(volatile int32_t *_Nonnull p, int32_t i) -{ - return (*p -= i); -} - -static OF_INLINE void *_Nullable -OFAtomicPointerSubtract(void *volatile _Nullable *_Nonnull p, intptr_t i) -{ - return (*(char *volatile *)p -= i); -} - -static OF_INLINE int -OFAtomicIntIncrease(volatile int *_Nonnull p) -{ - return ++*p; -} - -static OF_INLINE int32_t -OFAtomicInt32Increase(volatile int32_t *_Nonnull p) -{ - return ++*p; -} - -static OF_INLINE int -OFAtomicIntDecrease(volatile int *_Nonnull p) -{ - return --*p; -} - -static OF_INLINE int32_t -OFAtomicInt32Decrease(volatile int32_t *_Nonnull p) -{ - return --*p; -} - -static OF_INLINE unsigned int -OFAtomicIntOr(volatile unsigned int *_Nonnull p, unsigned int i) -{ - return (*p |= i); -} - -static OF_INLINE uint32_t -OFAtomicInt32Or(volatile uint32_t *_Nonnull p, uint32_t i) -{ - return (*p |= i); -} - -static OF_INLINE unsigned int -OFAtomicIntAnd(volatile unsigned int *_Nonnull p, unsigned int i) -{ - return (*p &= i); -} - -static OF_INLINE uint32_t -OFAtomicInt32And(volatile uint32_t *_Nonnull p, uint32_t i) -{ - return (*p &= i); -} - -static OF_INLINE unsigned int -OFAtomicIntXor(volatile unsigned int *_Nonnull p, unsigned int i) -{ - return (*p ^= i); -} - -static OF_INLINE uint32_t -OFAtomicInt32Xor(volatile uint32_t *_Nonnull p, uint32_t i) -{ - return (*p ^= i); -} - -static OF_INLINE bool -OFAtomicIntCompareAndSwap(volatile int *_Nonnull p, int o, int n) -{ - if (*p == o) { - *p = n; - return true; - } - - return false; -} - -static OF_INLINE bool -OFAtomicInt32CompareAndSwap(volatile int32_t *_Nonnull p, int32_t o, int32_t n) -{ - if (*p == o) { - *p = n; - return true; - } - - return false; -} - -static OF_INLINE bool -OFAtomicPointerCompareAndSwap(void *volatile _Nullable *_Nonnull p, - void *_Nullable o, void *_Nullable n) -{ - if (*p == o) { - *p = n; - return true; - } - - return false; -} - -static OF_INLINE void -OFMemoryBarrier(void) -{ - /* nop */ -} - -static OF_INLINE void -OFAcquireMemoryBarrier(void) -{ - /* nop */ -} - -static OF_INLINE void -OFReleaseMemoryBarrier(void) -{ - /* nop */ -} DELETED src/OFAtomic_osatomic.h Index: src/OFAtomic_osatomic.h ================================================================== --- src/OFAtomic_osatomic.h +++ src/OFAtomic_osatomic.h @@ -1,157 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include - -static OF_INLINE int -OFAtomicIntAdd(volatile int *_Nonnull p, int i) -{ - return OSAtomicAdd32(i, p); -} - -static OF_INLINE int32_t -OFAtomicInt32Add(volatile int32_t *_Nonnull p, int32_t i) -{ - return OSAtomicAdd32(i, p); -} - -static OF_INLINE void *_Nullable -OFAtomicPointerAdd(void *volatile _Nullable *_Nonnull p, intptr_t i) -{ -#ifdef __LP64__ - return (void *)OSAtomicAdd64(i, (int64_t *)p); -#else - return (void *)OSAtomicAdd32(i, (int32_t *)p); -#endif -} - -static OF_INLINE int -OFAtomicIntSubtract(volatile int *_Nonnull p, int i) -{ - return OSAtomicAdd32(-i, p); -} - -static OF_INLINE int32_t -OFAtomicInt32Subtract(volatile int32_t *_Nonnull p, int32_t i) -{ - return OSAtomicAdd32(-i, p); -} - -static OF_INLINE void *_Nullable -OFAtomicPointerSubtract(void *volatile _Nullable *_Nonnull p, intptr_t i) -{ -#ifdef __LP64__ - return (void *)OSAtomicAdd64(-i, (int64_t *)p); -#else - return (void *)OSAtomicAdd32(-i, (int32_t *)p); -#endif -} - -static OF_INLINE int -OFAtomicIntIncrease(volatile int *_Nonnull p) -{ - return OSAtomicIncrement32(p); -} - -static OF_INLINE int32_t -OFAtomicInt32Increase(volatile int32_t *_Nonnull p) -{ - return OSAtomicIncrement32(p); -} - -static OF_INLINE int -OFAtomicIntDecrease(volatile int *_Nonnull p) -{ - return OSAtomicDecrement32(p); -} - -static OF_INLINE int32_t -OFAtomicInt32Decrease(volatile int32_t *_Nonnull p) -{ - return OSAtomicDecrement32(p); -} - -static OF_INLINE unsigned int -OFAtomicIntOr(volatile unsigned int *_Nonnull p, unsigned int i) -{ - return OSAtomicOr32(i, p); -} - -static OF_INLINE uint32_t -OFAtomicInt32Or(volatile uint32_t *_Nonnull p, uint32_t i) -{ - return OSAtomicOr32(i, p); -} - -static OF_INLINE unsigned int -OFAtomicIntAnd(volatile unsigned int *_Nonnull p, unsigned int i) -{ - return OSAtomicAnd32(i, p); -} - -static OF_INLINE uint32_t -OFAtomicInt32And(volatile uint32_t *_Nonnull p, uint32_t i) -{ - return OSAtomicAnd32(i, p); -} - -static OF_INLINE unsigned int -OFAtomicIntXor(volatile unsigned int *_Nonnull p, unsigned int i) -{ - return OSAtomicXor32(i, p); -} - -static OF_INLINE uint32_t -OFAtomicInt32Xor(volatile uint32_t *_Nonnull p, uint32_t i) -{ - return OSAtomicXor32(i, p); -} - -static OF_INLINE bool -OFAtomicIntCompareAndSwap(volatile int *_Nonnull p, int o, int n) -{ - return OSAtomicCompareAndSwapInt(o, n, p); -} - -static OF_INLINE bool -OFAtomicInt32CompareAndSwap(volatile int32_t *_Nonnull p, int32_t o, int32_t n) -{ - return OSAtomicCompareAndSwap32(o, n, p); -} - -static OF_INLINE bool -OFAtomicPointerCompareAndSwap(void *volatile _Nullable *_Nonnull p, - void *_Nullable o, void *_Nullable n) -{ - return OSAtomicCompareAndSwapPtr(o, n, p); -} - -static OF_INLINE void -OFMemoryBarrier(void) -{ - OSMemoryBarrier(); -} - -static OF_INLINE void -OFAcquireMemoryBarrier(void) -{ - OSMemoryBarrier(); -} - -static OF_INLINE void -OFReleaseMemoryBarrier(void) -{ - OSMemoryBarrier(); -} DELETED src/OFAtomic_powerpc.h Index: src/OFAtomic_powerpc.h ================================================================== --- src/OFAtomic_powerpc.h +++ src/OFAtomic_powerpc.h @@ -1,397 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -static OF_INLINE int -OFAtomicIntAdd(volatile int *_Nonnull p, int i) -{ - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %2\n\t" - "add %0, %0, %1\n\t" - "stwcx. %0, 0, %2\n\t" - "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) - : "cc", "memory" - ); - - return i; -} - -static OF_INLINE int32_t -OFAtomicInt32Add(volatile int32_t *_Nonnull p, int32_t i) -{ - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %2\n\t" - "add %0, %0, %1\n\t" - "stwcx. %0, 0, %2\n\t" - "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) - : "cc", "memory" - ); - - return i; -} - -static OF_INLINE void *_Nullable -OFAtomicPointerAdd(void *volatile _Nullable *_Nonnull p, intptr_t i) -{ - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %2\n\t" - "add %0, %0, %1\n\t" - "stwcx. %0, 0, %2\n\t" - "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) - : "cc", "memory" - ); - - return (void *)i; -} - -static OF_INLINE int -OFAtomicIntSubtract(volatile int *_Nonnull p, int i) -{ - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %2\n\t" - "sub %0, %0, %1\n\t" - "stwcx. %0, 0, %2\n\t" - "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) - : "cc", "memory" - ); - - return i; -} - -static OF_INLINE int32_t -OFAtomicInt32Subtract(volatile int32_t *_Nonnull p, int32_t i) -{ - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %2\n\t" - "sub %0, %0, %1\n\t" - "stwcx. %0, 0, %2\n\t" - "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) - : "cc", "memory" - ); - - return i; -} - -static OF_INLINE void *_Nullable -OFAtomicPointerSubtract(void *volatile _Nullable *_Nonnull p, intptr_t i) -{ - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %2\n\t" - "sub %0, %0, %1\n\t" - "stwcx. %0, 0, %2\n\t" - "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) - : "cc", "memory" - ); - - return (void *)i; -} - -static OF_INLINE int -OFAtomicIntIncrease(volatile int *_Nonnull p) -{ - int i; - - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %1\n\t" - "addi %0, %0, 1\n\t" - "stwcx. %0, 0, %1\n\t" - "bne- 0b" - : "=&r"(i) - : "r"(p) - : "cc", "memory" - ); - - return i; -} - -static OF_INLINE int32_t -OFAtomicInt32Increase(volatile int32_t *_Nonnull p) -{ - int32_t i; - - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %1\n\t" - "addi %0, %0, 1\n\t" - "stwcx. %0, 0, %1\n\t" - "bne- 0b" - : "=&r"(i) - : "r"(p) - : "cc", "memory" - ); - - return i; -} - -static OF_INLINE int -OFAtomicIntDecrease(volatile int *_Nonnull p) -{ - int i; - - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %1\n\t" - "subi %0, %0, 1\n\t" - "stwcx. %0, 0, %1\n\t" - "bne- 0b" - : "=&r"(i) - : "r"(p) - : "cc", "memory" - ); - - return i; -} - -static OF_INLINE int32_t -OFAtomicInt32Decrease(volatile int32_t *_Nonnull p) -{ - int32_t i; - - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %1\n\t" - "subi %0, %0, 1\n\t" - "stwcx. %0, 0, %1\n\t" - "bne- 0b" - : "=&r"(i) - : "r"(p) - : "cc", "memory" - ); - - return i; -} - -static OF_INLINE unsigned int -OFAtomicIntOr(volatile unsigned int *_Nonnull p, unsigned int i) -{ - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %2\n\t" - "or %0, %0, %1\n\t" - "stwcx. %0, 0, %2\n\t" - "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) - : "cc", "memory" - ); - - return i; -} - -static OF_INLINE uint32_t -OFAtomicInt32Or(volatile uint32_t *_Nonnull p, uint32_t i) -{ - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %2\n\t" - "or %0, %0, %1\n\t" - "stwcx. %0, 0, %2\n\t" - "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) - : "cc", "memory" - ); - - return i; -} - -static OF_INLINE unsigned int -OFAtomicIntAnd(volatile unsigned int *_Nonnull p, unsigned int i) -{ - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %2\n\t" - "and %0, %0, %1\n\t" - "stwcx. %0, 0, %2\n\t" - "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) - : "cc", "memory" - ); - - return i; -} - -static OF_INLINE uint32_t -OFAtomicInt32And(volatile uint32_t *_Nonnull p, uint32_t i) -{ - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %2\n\t" - "and %0, %0, %1\n\t" - "stwcx. %0, 0, %2\n\t" - "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) - : "cc", "memory" - ); - - return i; -} - -static OF_INLINE unsigned int -OFAtomicIntXor(volatile unsigned int *_Nonnull p, unsigned int i) -{ - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %2\n\t" - "xor %0, %0, %1\n\t" - "stwcx. %0, 0, %2\n\t" - "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) - : "cc", "memory" - ); - - return i; -} - -static OF_INLINE uint32_t -OFAtomicInt32Xor(volatile uint32_t *_Nonnull p, uint32_t i) -{ - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %2\n\t" - "xor %0, %0, %1\n\t" - "stwcx. %0, 0, %2\n\t" - "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) - : "cc", "memory" - ); - - return i; -} - -static OF_INLINE bool -OFAtomicIntCompAndSwap(volatile int *_Nonnull p, int o, int n) -{ - int r; - - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %3\n\t" - "cmpw %0, %1\n\t" - "bne 1f\n\t" - "stwcx. %2, 0, %3\n\t" - "bne- 0b\n\t" - "li %0, 1\n\t" - "b 2f\n\t" - "1:\n\t" - "stwcx. %0, 0, %3\n\t" - "li %0, 0\n\t" - "2:" - : "=&r"(r) - : "r"(o), "r"(n), "r"(p) - : "cc", "memory" - ); - - return r; -} - -static OF_INLINE bool -OFAtomicInt32CompareAndSwap(volatile int32_t *_Nonnull p, int32_t o, int32_t n) -{ - int r; - - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %3\n\t" - "cmpw %0, %1\n\t" - "bne 1f\n\t" - "stwcx. %2, 0, %3\n\t" - "bne- 0b\n\t" - "li %0, 1\n\t" - "b 2f\n\t" - "1:\n\t" - "stwcx. %0, 0, %3\n\t" - "li %0, 0\n\t" - "2:" - : "=&r"(r) - : "r"(o), "r"(n), "r"(p) - : "cc", "memory" - ); - - return r; -} - -static OF_INLINE bool -OFAtomicPointerCompareAndSwap(void *volatile _Nullable *_Nonnull p, - void *_Nullable o, void *_Nullable n) -{ - int r; - - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %3\n\t" - "cmpw %0, %1\n\t" - "bne 1f\n\t" - "stwcx. %2, 0, %3\n\t" - "bne- 0b\n\t" - "li %0, 1\n\t" - "b 2f\n\t" - "1:\n\t" - "stwcx. %0, 0, %3\n\t" - "li %0, 0\n\t" - "2:" - : "=&r"(r) - : "r"(o), "r"(n), "r"(p) - : "cc", "memory" - ); - - return r; -} - -static OF_INLINE void -OFMemoryBarrier(void) -{ - __asm__ __volatile__ ( - ".long 0x7C2004AC /* lwsync */" ::: "memory" - ); -} - -static OF_INLINE void -OFAcquireMemoryBarrier(void) -{ - __asm__ __volatile__ ( - ".long 0x7C2004AC /* lwsync */" ::: "memory" - ); -} - -static OF_INLINE void -OFReleaseMemoryBarrier(void) -{ - __asm__ __volatile__ ( - ".long 0x7C2004AC /* lwsync */" ::: "memory" - ); -} DELETED src/OFAtomic_sync_builtins.h Index: src/OFAtomic_sync_builtins.h ================================================================== --- src/OFAtomic_sync_builtins.h +++ src/OFAtomic_sync_builtins.h @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -static OF_INLINE int -OFAtomicIntAdd(volatile int *_Nonnull p, int i) -{ - return __sync_add_and_fetch(p, i); -} - -static OF_INLINE int32_t -OFAtomicInt32Add(volatile int32_t *_Nonnull p, int32_t i) -{ - return __sync_add_and_fetch(p, i); -} - -static OF_INLINE void *_Nullable -OFAtomicPointerAdd(void *volatile _Nullable *_Nonnull p, intptr_t i) -{ - return __sync_add_and_fetch(p, (void *)i); -} - -static OF_INLINE int -OFAtomicIntSubtract(volatile int *_Nonnull p, int i) -{ - return __sync_sub_and_fetch(p, i); -} - -static OF_INLINE int32_t -OFAtomicInt32Subtract(volatile int32_t *_Nonnull p, int32_t i) -{ - return __sync_sub_and_fetch(p, i); -} - -static OF_INLINE void *_Nullable -OFAtomicPointerSubtract(void *volatile _Nullable *_Nonnull p, intptr_t i) -{ - return __sync_sub_and_fetch(p, (void *)i); -} - -static OF_INLINE int -OFAtomicIntIncrease(volatile int *_Nonnull p) -{ - return __sync_add_and_fetch(p, 1); -} - -static OF_INLINE int32_t -OFAtomicInt32Increase(volatile int32_t *_Nonnull p) -{ - return __sync_add_and_fetch(p, 1); -} - -static OF_INLINE int -OFAtomicIntDecrease(volatile int *_Nonnull p) -{ - return __sync_sub_and_fetch(p, 1); -} - -static OF_INLINE int32_t -OFAtomicInt32Decrease(volatile int32_t *_Nonnull p) -{ - return __sync_sub_and_fetch(p, 1); -} - -static OF_INLINE unsigned int -OFAtomicIntOr(volatile unsigned int *_Nonnull p, unsigned int i) -{ - return __sync_or_and_fetch(p, i); -} - -static OF_INLINE uint32_t -OFAtomicInt32Or(volatile uint32_t *_Nonnull p, uint32_t i) -{ - return __sync_or_and_fetch(p, i); -} - -static OF_INLINE unsigned int -OFAtomicIntAnd(volatile unsigned int *_Nonnull p, unsigned int i) -{ - return __sync_and_and_fetch(p, i); -} - -static OF_INLINE uint32_t -OFAtomicInt32And(volatile uint32_t *_Nonnull p, uint32_t i) -{ - return __sync_and_and_fetch(p, i); -} - -static OF_INLINE unsigned int -OFAtomicIntXor(volatile unsigned int *_Nonnull p, unsigned int i) -{ - return __sync_xor_and_fetch(p, i); -} - -static OF_INLINE uint32_t -OFAtomicInt32Xor(volatile uint32_t *_Nonnull p, uint32_t i) -{ - return __sync_xor_and_fetch(p, i); -} - -static OF_INLINE bool -OFAtomicIntCompareAndSwap(volatile int *_Nonnull p, int o, int n) -{ - return __sync_bool_compare_and_swap(p, o, n); -} - -static OF_INLINE bool -OFAtomicInt32CompAndSwap(volatile int32_t *_Nonnull p, int32_t o, int32_t n) -{ - return __sync_bool_compare_and_swap(p, o, n); -} - -static OF_INLINE bool -OFAtomicPointerCompareAndSwap(void *volatile _Nullable *_Nonnull p, - void *_Nullable o, void *_Nullable n) -{ - return __sync_bool_compare_and_swap(p, o, n); -} - -static OF_INLINE void -OFMemoryBarrier(void) -{ - __sync_synchronize(); -} - -static OF_INLINE void -OFAcquireMemoryBarrier(void) -{ - __sync_synchronize(); -} - -static OF_INLINE void -OFReleaseMemoryBarrier(void) -{ - __sync_synchronize(); -} DELETED src/OFAtomic_x86.h Index: src/OFAtomic_x86.h ================================================================== --- src/OFAtomic_x86.h +++ src/OFAtomic_x86.h @@ -1,502 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -OF_ASSUME_NONNULL_BEGIN - -static OF_INLINE int -OFAtomicIntAdd(volatile int *_Nonnull p, int i) -{ - if (sizeof(int) == 4) - __asm__ __volatile__ ( - "lock\n\t" - "xaddl %0, %2\n\t" - "addl %1, %0" - : "+&r"(i) - : "r"(i), "m"(*p) - ); -#ifdef OF_X86_64 - else if (sizeof(int) == 8) - __asm__ __volatile__ ( - "lock\n\t" - "xaddq %0, %2\n\t" - "addq %1, %0" - : "+&r"(i) - : "r"(i), "m"(*p) - ); -#endif - else - abort(); - - return i; -} - -static OF_INLINE int32_t -OFAtomicInt32Add(volatile int32_t *_Nonnull p, int32_t i) -{ - __asm__ __volatile__ ( - "lock\n\t" - "xaddl %0, %2\n\t" - "addl %1, %0" - : "+&r"(i) - : "r"(i), "m"(*p) - ); - - return i; -} - -static OF_INLINE void *_Nullable -OFAtomicPointerAdd(void *volatile _Nullable *_Nonnull p, intptr_t i) -{ -#if defined(OF_X86_64) - __asm__ __volatile__ ( - "lock\n\t" - "xaddq %0, %2\n\t" - "addq %1, %0" - : "+&r"(i) - : "r"(i), "m"(*p) - ); - - return (void *)i; -#elif defined(OF_X86) - __asm__ __volatile__ ( - "lock\n\t" - "xaddl %0, %2\n\t" - "addl %1, %0" - : "+&r"(i) - : "r"(i), "m"(*p) - ); - - return (void *)i; -#endif -} - -static OF_INLINE int -OFAtomicIntSubtract(volatile int *_Nonnull p, int i) -{ - if (sizeof(int) == 4) - __asm__ __volatile__ ( - "negl %0\n\t" - "lock\n\t" - "xaddl %0, %2\n\t" - "subl %1, %0" - : "+&r"(i) - : "r"(i), "m"(*p) - ); -#ifdef OF_X86_64 - else if (sizeof(int) == 8) - __asm__ __volatile__ ( - "negq %0\n\t" - "lock\n\t" - "xaddq %0, %2\n\t" - "subq %1, %0" - : "+&r"(i) - : "r"(i), "m"(*p) - ); -#endif - else - abort(); - - return i; -} - -static OF_INLINE int32_t -OFAtomicInt32Subtract(volatile int32_t *_Nonnull p, int32_t i) -{ - __asm__ __volatile__ ( - "negl %0\n\t" - "lock\n\t" - "xaddl %0, %2\n\t" - "subl %1, %0" - : "+&r"(i) - : "r"(i), "m"(*p) - ); - - return i; -} - -static OF_INLINE void *_Nullable -OFAtomicPointerSubtract(void *volatile _Nullable *_Nonnull p, intptr_t i) -{ -#if defined(OF_X86_64) - __asm__ __volatile__ ( - "negq %0\n\t" - "lock\n\t" - "xaddq %0, %2\n\t" - "subq %1, %0" - : "+&r"(i) - : "r"(i), "m"(*p) - ); - - return (void *)i; -#elif defined(OF_X86) - __asm__ __volatile__ ( - "negl %0\n\t" - "lock\n\t" - "xaddl %0, %2\n\t" - "subl %1, %0" - : "+&r"(i) - : "r"(i), "m"(*p) - ); - - return (void *)i; -#endif -} - -static OF_INLINE int -OFAtomicIntIncrease(volatile int *_Nonnull p) -{ - int i; - - if (sizeof(int) == 4) - __asm__ __volatile__ ( - "xorl %0, %0\n\t" - "incl %0\n\t" - "lock\n\t" - "xaddl %0, %1\n\t" - "incl %0" - : "=&r"(i) - : "m"(*p) - ); -#ifdef OF_X86_64 - else if (sizeof(int) == 8) - __asm__ __volatile__ ( - "xorq %0, %0\n\t" - "incq %0\n\t" - "lock\n\t" - "xaddq %0, %1\n\t" - "incq %0" - : "=&r"(i) - : "m"(*p) - ); -#endif - else - abort(); - - return i; -} - -static OF_INLINE int32_t -OFAtomicInt32Increase(volatile int32_t *_Nonnull p) -{ - int32_t i; - - __asm__ __volatile__ ( - "xorl %0, %0\n\t" - "incl %0\n\t" - "lock\n\t" - "xaddl %0, %1\n\t" - "incl %0" - : "=&r"(i) - : "m"(*p) - ); - - return i; -} - -static OF_INLINE int -OFAtomicIntDecrease(volatile int *_Nonnull p) -{ - int i; - - if (sizeof(int) == 4) - __asm__ __volatile__ ( - "xorl %0, %0\n\t" - "decl %0\n\t" - "lock\n\t" - "xaddl %0, %1\n\t" - "decl %0" - : "=&r"(i) - : "m"(*p) - ); -#ifdef OF_X86_64 - else if (sizeof(int) == 8) - __asm__ __volatile__ ( - "xorq %0, %0\n\t" - "decq %0\n\t" - "lock\n\t" - "xaddq %0, %1\n\t" - "decq %0" - : "=&r"(i) - : "m"(*p) - ); -#endif - else - abort(); - - return i; -} - -static OF_INLINE int32_t -OFAtomicInt32Decrease(volatile int32_t *_Nonnull p) -{ - int32_t i; - - __asm__ __volatile__ ( - "xorl %0, %0\n\t" - "decl %0\n\t" - "lock\n\t" - "xaddl %0, %1\n\t" - "decl %0" - : "=&r"(i) - : "m"(*p) - ); - - return i; -} - -static OF_INLINE unsigned int -OFAtomicIntOr(volatile unsigned int *_Nonnull p, unsigned int i) -{ - if (sizeof(int) == 4) - __asm__ __volatile__ ( - "0:\n\t" - "movl %2, %0\n\t" - "movl %0, %%eax\n\t" - "orl %1, %0\n\t" - "lock\n\t" - "cmpxchg %0, %2\n\t" - "jne 0b" - : "=&r"(i) - : "r"(i), "m"(*p) - : "eax", "cc" - ); -#ifdef OF_X86_64 - else if (sizeof(int) == 8) - __asm__ __volatile__ ( - "0:\n\t" - "movq %2, %0\n\t" - "movq %0, %%rax\n\t" - "orq %1, %0\n\t" - "lock\n\t" - "cmpxchg %0, %2\n\t" - "jne 0b" - : "=&r"(i) - : "r"(i), "m"(*p) - : "rax", "cc" - ); -#endif - else - abort(); - - return i; -} - -static OF_INLINE uint32_t -OFAtomicInt32Or(volatile uint32_t *_Nonnull p, uint32_t i) -{ - __asm__ __volatile__ ( - "0:\n\t" - "movl %2, %0\n\t" - "movl %0, %%eax\n\t" - "orl %1, %0\n\t" - "lock\n\t" - "cmpxchg %0, %2\n\t" - "jne 0b" - : "=&r"(i) - : "r"(i), "m"(*p) - : "eax", "cc" - ); - - return i; -} - -static OF_INLINE unsigned int -OFAtomicIntAnd(volatile unsigned int *_Nonnull p, unsigned int i) -{ - if (sizeof(int) == 4) - __asm__ __volatile__ ( - "0:\n\t" - "movl %2, %0\n\t" - "movl %0, %%eax\n\t" - "andl %1, %0\n\t" - "lock\n\t" - "cmpxchg %0, %2\n\t" - "jne 0b" - : "=&r"(i) - : "r"(i), "m"(*p) - : "eax", "cc" - ); -#ifdef OF_X86_64 - else if (sizeof(int) == 8) - __asm__ __volatile__ ( - "0:\n\t" - "movq %2, %0\n\t" - "movq %0, %%rax\n\t" - "andq %1, %0\n\t" - "lock\n\t" - "cmpxchg %0, %2\n\t" - "jne 0b" - : "=&r"(i) - : "r"(i), "m"(*p) - : "rax", "cc" - ); -#endif - else - abort(); - - return i; -} - -static OF_INLINE uint32_t -OFAtomicInt32And(volatile uint32_t *_Nonnull p, uint32_t i) -{ - __asm__ __volatile__ ( - "0:\n\t" - "movl %2, %0\n\t" - "movl %0, %%eax\n\t" - "andl %1, %0\n\t" - "lock\n\t" - "cmpxchg %0, %2\n\t" - "jne 0b" - : "=&r"(i) - : "r"(i), "m"(*p) - : "eax", "cc" - ); - - return i; -} - -static OF_INLINE unsigned int -OFAtomicIntXor(volatile unsigned int *_Nonnull p, unsigned int i) -{ - if (sizeof(int) == 4) - __asm__ __volatile__ ( - "0:\n\t" - "movl %2, %0\n\t" - "movl %0, %%eax\n\t" - "xorl %1, %0\n\t" - "lock\n\t" - "cmpxchg %0, %2\n\t" - "jne 0b" - : "=&r"(i) - : "r"(i), "m"(*p) - : "eax", "cc" - ); -#ifdef OF_X86_64 - else if (sizeof(int) == 8) - __asm__ __volatile__ ( - "0:\n\t" - "movq %2, %0\n\t" - "movq %0, %%rax\n\t" - "xorq %1, %0\n\t" - "lock\n\t" - "cmpxchg %0, %2\n\t" - "jne 0b" - : "=&r"(i) - : "r"(i), "m"(*p) - : "rax", "cc" - ); -#endif - else - abort(); - - return i; -} - -static OF_INLINE uint32_t -OFAtomicInt32Xor(volatile uint32_t *_Nonnull p, uint32_t i) -{ - __asm__ __volatile__ ( - "0:\n\t" - "movl %2, %0\n\t" - "movl %0, %%eax\n\t" - "xorl %1, %0\n\t" - "lock\n\t" - "cmpxchgl %0, %2\n\t" - "jne 0b" - : "=&r"(i) - : "r"(i), "m"(*p) - : "eax", "cc" - ); - - return i; -} - -static OF_INLINE bool -OFAtomicIntCompareAndSwap(volatile int *_Nonnull p, int o, int n) -{ - int r; - - __asm__ __volatile__ ( - "lock\n\t" - "cmpxchg %2, %3\n\t" - "sete %b0\n\t" - "movzbl %b0, %0" - : "=&d"(r), "+a"(o) /* use d instead of r to avoid a gcc bug */ - : "r"(n), "m"(*p) - : "cc" - ); - - return r; -} - -static OF_INLINE bool -OFAtomicInt32CompareAndSwap(volatile int32_t *_Nonnull p, int32_t o, int32_t n) -{ - int r; - - __asm__ __volatile__ ( - "lock\n\t" - "cmpxchg %2, %3\n\t" - "sete %b0\n\t" - "movzbl %b0, %0" - : "=&d"(r), "+a"(o) /* use d instead of r to avoid a gcc bug */ - : "r"(n), "m"(*p) - : "cc" - ); - - return r; -} - -static OF_INLINE bool -OFAtomicPointerCompareAndSwap(void *volatile _Nullable *_Nonnull p, - void *_Nullable o, void *_Nullable n) -{ - int r; - - __asm__ __volatile__ ( - "lock\n\t" - "cmpxchg %2, %3\n\t" - "sete %b0\n\t" - "movzbl %b0, %0" - : "=&d"(r), "+a"(o) /* use d instead of r to avoid a gcc bug */ - : "r"(n), "m"(*p) - : "cc" - ); - - return r; -} - -static OF_INLINE void -OFMemoryBarrier(void) -{ - __asm__ __volatile__ ( - "mfence" ::: "memory" - ); -} - -static OF_INLINE void -OFAcquireMemoryBarrier(void) -{ - __asm__ __volatile__ ("" ::: "memory"); -} - -static OF_INLINE void -OFReleaseMemoryBarrier(void) -{ - __asm__ __volatile__ ("" ::: "memory"); -} - -OF_ASSUME_NONNULL_END Index: src/OFBlock.h ================================================================== --- src/OFBlock.h +++ src/OFBlock.h @@ -40,12 +40,12 @@ @end #ifdef __cplusplus extern "C" { #endif -extern void *_Block_copy(const void *); -extern void _Block_release(const void *); +extern void *_Nullable _Block_copy(const void *_Nullable); +extern void _Block_release(const void *_Nullable); # if defined(OF_WINDOWS) && \ (defined(OF_NO_SHARED) || defined(OF_COMPILING_OBJFW)) /* * Clang has implicit declarations for these, but they are dllimport. When Index: src/OFCondition.m ================================================================== --- src/OFCondition.m +++ src/OFCondition.m @@ -104,11 +104,11 @@ #ifdef OF_AMIGAOS - (bool)waitForTimeInterval: (OFTimeInterval)timeInterval orExecSignal: (ULONG *)signalMask { - int error = OFPlainConditionTimedWaitExecOrSignal(&_condition, &_mutex, + int error = OFPlainConditionTimedWaitOrExecSignal(&_condition, &_mutex, timeInterval, signalMask); if (error == ETIMEDOUT) return false; Index: src/OFDNSResolverSettings.m ================================================================== --- src/OFDNSResolverSettings.m +++ src/OFDNSResolverSettings.m @@ -69,10 +69,12 @@ #ifndef OF_WII static OFString * domainFromHostname(OFString *hostname) { + OFString *ret; + if (hostname == nil) return nil; @try { OFSocketAddressParseIP(hostname, 0); @@ -79,20 +81,22 @@ /* * If we are still here, the host name is a valid IP address. * We can't use that as local domain. */ - return nil; + ret = nil; } @catch (OFInvalidFormatException *e) { /* Not an IP address -> we can use it if it contains a dot. */ size_t pos = [hostname rangeOfString: @"."].location; - if (pos == OFNotFound) - return nil; - - return [hostname substringFromIndex: pos + 1]; + if (pos != OFNotFound) + ret = [hostname substringFromIndex: pos + 1]; + else + ret = nil; } + + return ret; } #endif #if !defined(OF_WII) && !defined(OF_MORPHOS) static OFString * Index: src/OFDNSResourceRecord.h ================================================================== --- src/OFDNSResourceRecord.h +++ src/OFDNSResourceRecord.h @@ -618,14 +618,41 @@ @end #ifdef __cplusplus extern "C" { #endif +/** + * @brief Returns the name for the specified OFDNSClass. + * + * @param DNSClass The OFDNSClass to return the name for + * @return The name for the specified OFDNSClass + */ extern OFString *_Nonnull OFDNSClassName(OFDNSClass DNSClass); + +/** + * @brief Returns the name for the specified OFDNSRecordType. + * + * @param recordType The OFDNSRecordType to return the name for + * @return The name for the specified OFDNSRecordType + */ extern OFString *_Nonnull OFDNSRecordTypeName(OFDNSRecordType recordType); + +/** + * @brief Parses the specified string as an @ref OFDNSClass. + * + * @param string The string to parse as an @ref OFDNSClass + * @return The parsed OFDNSClass + */ extern OFDNSClass OFDNSClassParseName(OFString *_Nonnull string); + +/** + * @brief Parses the specified string as an @ref OFDNSRecordType. + * + * @param string The string to parse as an @ref OFDNSRecordType + * @return The parsed OFDNSRecordType + */ extern OFDNSRecordType OFDNSRecordTypeParseName(OFString *_Nonnull string); #ifdef __cplusplus } #endif OF_ASSUME_NONNULL_END Index: src/OFData.h ================================================================== --- src/OFData.h +++ src/OFData.h @@ -118,10 +118,13 @@ itemSize: (size_t)itemSize; /** * @brief Creates a new OFData with the specified `count` items of size 1 by * taking over ownership of the specified items pointer. + * + * If initialization fails for whatever reason, the passed memory is *not* + * free'd if `freeWhenDone` is true. * * @param items The items to store in the OFData * @param count The number of items * @param freeWhenDone Whether to free the pointer when it is no longer needed * by the OFData @@ -132,10 +135,13 @@ freeWhenDone: (bool)freeWhenDone; /** * @brief Creates a new OFData with the specified `count` items of the * specified size by taking ownership of the specified items pointer. + * + * If initialization fails for whatever reason, the passed memory is *not* + * free'd if `freeWhenDone` is true. * * @param items The items to store in the OFData * @param count The number of items * @param itemSize The item size of a single item in bytes * @param freeWhenDone Whether to free the pointer when it is no longer needed @@ -210,10 +216,13 @@ /** * @brief Initializes an already allocated OFData with the specified `count` * items of size 1 by taking over ownership of the specified items * pointer. + * + * If initialization fails for whatever reason, the passed memory is *not* + * free'd if `freeWhenDone` is true. * * @param items The items to store in the OFData * @param count The number of items * @param freeWhenDone Whether to free the pointer when it is no longer needed * by the OFData @@ -225,10 +234,13 @@ /** * @brief Initializes an already allocated OFData with the specified `count` * items of the specified size by taking ownership of the specified * items pointer. + * + * If initialization fails for whatever reason, the passed memory is *not* + * free'd if `freeWhenDone` is true. * * @param items The items to store in the OFData * @param count The number of items * @param itemSize The item size of a single item in bytes * @param freeWhenDone Whether to free the pointer when it is no longer needed Index: src/OFDatagramSocket.m ================================================================== --- src/OFDatagramSocket.m +++ src/OFDatagramSocket.m @@ -116,11 +116,11 @@ @throw [OFSetOptionFailedException exceptionWithObject: self errNo: errno]; _canBlock = canBlock; #elif defined(OF_WINDOWS) - u_long v = canBlock; + u_long v = !canBlock; if (ioctlsocket(_socket, FIONBIO, &v) == SOCKET_ERROR) @throw [OFSetOptionFailedException exceptionWithObject: self errNo: OFSocketErrNo()]; Index: src/OFFile.m ================================================================== --- src/OFFile.m +++ src/OFFile.m @@ -77,28 +77,32 @@ #endif #ifndef OF_AMIGAOS # define closeHandle(h) close(h) #else -static struct _OFFileHandle +static struct _OFFileHandle { struct _OFFileHandle *previous, *next; BPTR handle; bool append; } *firstHandle = NULL; static void closeHandle(OFFileHandle handle) { Close(handle->handle); + + Forbid(); if (handle->previous != NULL) handle->previous->next = handle->next; if (handle->next != NULL) handle->next->previous = handle->previous; if (firstHandle == handle) firstHandle = handle->next; + + Permit(); OFFreeMemory(handle); } OF_DESTRUCTOR() @@ -289,18 +293,22 @@ exceptionWithPath: path mode: mode errNo: EIO]; } } + + Forbid(); handle->previous = NULL; handle->next = firstHandle; if (firstHandle != NULL) firstHandle->previous = handle; firstHandle = handle; + + Permit(); } @catch (id e) { OFFreeMemory(handle); @throw e; } #endif Index: src/OFFileManager.h ================================================================== --- src/OFFileManager.h +++ src/OFFileManager.h @@ -406,10 +406,21 @@ * @param URL The URL to the directory whose items should be returned * @return An array with the URLs of the items in the specified directory */ - (OFArray OF_GENERIC(OFURL *) *)contentsOfDirectoryAtURL: (OFURL *)URL; +/** + * @brief Returns an array with all subpaths of the specified directory. + * + * @note `.` and `..` (of the directory itself or any subdirectory) are not + * part of the returned array. + * + * @param path The path to the directory whose subpaths should be returned + * @return An array of OFString with the subpaths of the specified directory + */ +- (OFArray OF_GENERIC(OFString *) *)subpathsOfDirectoryAtPath: (OFString *)path; + #ifdef OF_HAVE_FILES /** * @brief Changes the current working directory. * * @param path The new directory to change to Index: src/OFFileManager.m ================================================================== --- src/OFFileManager.m +++ src/OFFileManager.m @@ -69,39 +69,15 @@ #endif @interface OFDefaultFileManager: OFFileManager @end -const OFFileAttributeKey OFFileSize = @"OFFileSize"; -const OFFileAttributeKey OFFileType = @"OFFileType"; -const OFFileAttributeKey OFFilePOSIXPermissions = @"OFFilePOSIXPermissions"; -const OFFileAttributeKey OFFileOwnerAccountID = @"OFFileOwnerAccountID"; -const OFFileAttributeKey OFFileGroupOwnerAccountID = - @"OFFileGroupOwnerAccountID"; -const OFFileAttributeKey OFFileOwnerAccountName = @"OFFileOwnerAccountName"; -const OFFileAttributeKey OFFileGroupOwnerAccountName = - @"OFFileGroupOwnerAccountName"; -const OFFileAttributeKey OFFileLastAccessDate = @"OFFileLastAccessDate"; -const OFFileAttributeKey OFFileModificationDate = @"OFFileModificationDate"; -const OFFileAttributeKey OFFileStatusChangeDate = @"OFFileStatusChangeDate"; -const OFFileAttributeKey OFFileCreationDate = @"OFFileCreationDate"; -const OFFileAttributeKey OFFileSymbolicLinkDestination = - @"OFFileSymbolicLinkDestination"; - -const OFFileAttributeType OFFileTypeRegular = @"OFFileTypeRegular"; -const OFFileAttributeType OFFileTypeDirectory = @"OFFileTypeDirectory"; -const OFFileAttributeType OFFileTypeSymbolicLink = @"OFFileTypeSymbolicLink"; -const OFFileAttributeType OFFileTypeFIFO = @"OFFileTypeFIFO"; -const OFFileAttributeType OFFileTypeCharacterSpecial = - @"OFFileTypeCharacterSpecial"; -const OFFileAttributeType OFFileTypeBlockSpecial = @"OFFileTypeBlockSpecial"; -const OFFileAttributeType OFFileTypeSocket = @"OFFileTypeSocket"; -const OFFileAttributeType OFFileTypeUnknown = @"OFFileTypeUnknown"; - #ifdef OF_AMIGAOS4 # define CurrentDir(lock) SetCurrentDir(lock) #endif + +#include "OFFileManagerConstants.inc" static OFFileManager *defaultManager; #ifdef OF_AMIGAOS static bool dirChanged = false; @@ -470,10 +446,41 @@ ret = [OFMutableArray arrayWithCapacity: URLs.count]; for (OFURL *URL in URLs) [ret addObject: URL.lastPathComponent]; + [ret makeImmutable]; + [ret retain]; + + objc_autoreleasePoolPop(pool); + + return [ret autorelease]; +} + +- (OFArray OF_GENERIC(OFString *) *)subpathsOfDirectoryAtPath: (OFString *)path +{ + void *pool = objc_autoreleasePoolPush(); + OFMutableArray OF_GENERIC(OFString *) *ret = + [OFMutableArray arrayWithObject: path]; + + for (OFString *subpath in [self contentsOfDirectoryAtPath: path]) { + void *pool2 = objc_autoreleasePoolPush(); + OFString *fullSubpath = + [path stringByAppendingPathComponent: subpath]; + OFFileAttributes attributes = + [self attributesOfItemAtPath: fullSubpath]; + + if ([attributes.fileType isEqual: OFFileTypeDirectory]) + [ret addObjectsFromArray: + [self subpathsOfDirectoryAtPath: fullSubpath]]; + else + [ret addObject: fullSubpath]; + + objc_autoreleasePoolPop(pool2); + } + + [ret makeImmutable]; [ret retain]; objc_autoreleasePoolPop(pool); return [ret autorelease]; ADDED src/OFFileManagerConstants.inc Index: src/OFFileManagerConstants.inc ================================================================== --- src/OFFileManagerConstants.inc +++ src/OFFileManagerConstants.inc @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2008-2021 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +const OFFileAttributeKey OFFileSize = @"OFFileSize"; +const OFFileAttributeKey OFFileType = @"OFFileType"; +const OFFileAttributeKey OFFilePOSIXPermissions = @"OFFilePOSIXPermissions"; +const OFFileAttributeKey OFFileOwnerAccountID = @"OFFileOwnerAccountID"; +const OFFileAttributeKey OFFileGroupOwnerAccountID = + @"OFFileGroupOwnerAccountID"; +const OFFileAttributeKey OFFileOwnerAccountName = @"OFFileOwnerAccountName"; +const OFFileAttributeKey OFFileGroupOwnerAccountName = + @"OFFileGroupOwnerAccountName"; +const OFFileAttributeKey OFFileLastAccessDate = @"OFFileLastAccessDate"; +const OFFileAttributeKey OFFileModificationDate = @"OFFileModificationDate"; +const OFFileAttributeKey OFFileStatusChangeDate = @"OFFileStatusChangeDate"; +const OFFileAttributeKey OFFileCreationDate = @"OFFileCreationDate"; +const OFFileAttributeKey OFFileSymbolicLinkDestination = + @"OFFileSymbolicLinkDestination"; + +const OFFileAttributeType OFFileTypeRegular = @"OFFileTypeRegular"; +const OFFileAttributeType OFFileTypeDirectory = @"OFFileTypeDirectory"; +const OFFileAttributeType OFFileTypeSymbolicLink = @"OFFileTypeSymbolicLink"; +const OFFileAttributeType OFFileTypeFIFO = @"OFFileTypeFIFO"; +const OFFileAttributeType OFFileTypeCharacterSpecial = + @"OFFileTypeCharacterSpecial"; +const OFFileAttributeType OFFileTypeBlockSpecial = @"OFFileTypeBlockSpecial"; +const OFFileAttributeType OFFileTypeSocket = @"OFFileTypeSocket"; +const OFFileAttributeType OFFileTypeUnknown = @"OFFileTypeUnknown"; Index: src/OFHTTPServer.m ================================================================== --- src/OFHTTPServer.m +++ src/OFHTTPServer.m @@ -114,16 +114,17 @@ @interface OFHTTPServerThread: OFThread - (void)stop; @end #endif -static OF_INLINE OFString * +static OFString * normalizedKey(OFString *key) { char *cString = OFStrDup(key.UTF8String); unsigned char *tmp = (unsigned char *)cString; bool firstLetter = true; + OFString *ret; while (*tmp != '\0') { if (!OFASCIIIsAlpha(*tmp)) { firstLetter = true; tmp++; @@ -136,16 +137,18 @@ firstLetter = false; tmp++; } @try { - return [OFString stringWithUTF8StringNoCopy: cString - freeWhenDone: true]; + ret = [OFString stringWithUTF8StringNoCopy: cString + freeWhenDone: true]; } @catch (id e) { OFFreeMemory(cString); @throw e; } + + return ret; } @implementation OFHTTPServerResponse - (instancetype)initWithSocket: (OFStreamSocket *)sock server: (OFHTTPServer *)server Index: src/OFIPSocketAsyncConnector.m ================================================================== --- src/OFIPSocketAsyncConnector.m +++ src/OFIPSocketAsyncConnector.m @@ -171,11 +171,15 @@ [_socket setCanBlock: false]; #endif if (![_socket of_connectSocketToAddress: &address errNo: &errNo]) { #if !defined(OF_NINTENDO_3DS) && !defined(OF_WII) +# ifdef OF_WINDOWS + if (errNo == EINPROGRESS || errNo == EWOULDBLOCK) { +# else if (errNo == EINPROGRESS) { +# endif [OFRunLoop of_addAsyncConnectForSocket: _socket mode: runLoopMode delegate: self]; return; } else { Index: src/OFList.h ================================================================== --- src/OFList.h +++ src/OFList.h @@ -49,20 +49,20 @@ * @brief Returns the next list item of the list item. * * @param listItem The list item for which the next list item should be returned * @return The next list item of the list item */ -OFListItem OFListItemNext(OFListItem _Nonnull listItem); +extern OFListItem _Nullable OFListItemNext(OFListItem _Nonnull listItem); /*! * @brief Returns the previous list item of the list item. * * @param listItem The list item for which the previous list item should be * returned * @return The previous list item of the list item */ -OFListItem OFListItemPrevious(OFListItem _Nonnull listItem); +extern OFListItem _Nullable OFListItemPrevious(OFListItem _Nonnull listItem); /*! * @brief Returns the object of the list item. * * @warning The returned object is not retained and autoreleased - this is the @@ -69,11 +69,11 @@ * caller's responsibility! * * @param listItem The list item for which the object should be returned * @return The object of the list item */ -id OFListItemObject(OFListItem _Nonnull listItem); +extern id _Nonnull OFListItemObject(OFListItem _Nonnull listItem); #ifdef __cplusplus } #endif /** Index: src/OFLocale.m ================================================================== --- src/OFLocale.m +++ src/OFLocale.m @@ -424,11 +424,11 @@ if (0) { # endif OFStringEncoding ASCII = OFStringEncodingASCII; @try { - _encoding = OFStringEncodingForName( + _encoding = OFStringEncodingParseName( [OFString stringWithCString: buffer encoding: ASCII]); } @catch (OFInvalidArgumentException *e) { _encoding = OFStringEncodingISO8859_1; } Index: src/OFObject.h ================================================================== --- src/OFObject.h +++ src/OFObject.h @@ -627,14 +627,13 @@ * * Derived classes can override this to execute their own code when the class * is unloaded. * * @warning This is not supported by the Apple runtime and currently only - * called by the ObjFW runtime when objc_unregister_class() or - * objc_exit() has been called! + * called by the ObjFW runtime when @ref objc_deinit has been called! * In the future, this might also be called by the ObjFW runtime when - * the class is part of a plugin that has been unloaded. + * the class is part of a plugin that is being unloaded. */ + (void)unload; /** * @brief A method which is called the moment before the first call to the class Index: src/OFObject.m ================================================================== --- src/OFObject.m +++ src/OFObject.m @@ -70,11 +70,11 @@ #ifdef OF_APPLE_RUNTIME extern id _Nullable _objc_rootAutorelease(id _Nullable object); #endif #if defined(OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR) extern id OFForward(id, SEL, ...); -extern struct stret OFForward_stret(id, SEL, ...); +extern struct Stret OFForward_stret(id, SEL, ...); #else # define OFForward OFMethodNotFound # define OFForward_stret OFMethodNotFound_stret #endif Index: src/OFPlainCondition.m ================================================================== --- src/OFPlainCondition.m +++ src/OFPlainCondition.m @@ -16,11 +16,11 @@ #include "config.h" #include "platform.h" #if defined(OF_HAVE_PTHREADS) -# include "platform/posix/OFPlainCondition.m" +# include "platform/POSIX/OFPlainCondition.m" #elif defined(OF_WINDOWS) -# include "platform/windows/OFPlainCondition.m" +# include "platform/Windows/OFPlainCondition.m" #elif defined(OF_AMIGAOS) -# include "platform/amiga/OFPlainCondition.m" +# include "platform/AmigaOS/OFPlainCondition.m" #endif Index: src/OFPlainMutex.m ================================================================== --- src/OFPlainMutex.m +++ src/OFPlainMutex.m @@ -16,11 +16,11 @@ #include "config.h" #include "platform.h" #if defined(OF_HAVE_PTHREADS) -# include "platform/posix/OFPlainMutex.m" +# include "platform/POSIX/OFPlainMutex.m" #elif defined(OF_WINDOWS) -# include "platform/windows/OFPlainMutex.m" +# include "platform/Windows/OFPlainMutex.m" #elif defined(OF_AMIGAOS) -# include "platform/amiga/OFPlainMutex.m" +# include "platform/AmigaOS/OFPlainMutex.m" #endif Index: src/OFPlainThread.h ================================================================== --- src/OFPlainThread.h +++ src/OFPlainThread.h @@ -73,16 +73,11 @@ { return (thread == GetCurrentThread()); } #elif defined(OF_AMIGAOS) extern OFPlainThread OFCurrentPlainThread(void); - -static OF_INLINE bool -OFPlainThreadIsCurrent(OFPlainThread thread) -{ - return (thread->thread == FindTask(NULL)); -} +extern bool OFPlainThreadIsCurrent(OFPlainThread); #endif #ifdef __cplusplus extern "C" { #endif Index: src/OFPlainThread.m ================================================================== --- src/OFPlainThread.m +++ src/OFPlainThread.m @@ -16,11 +16,11 @@ #include "config.h" #include "platform.h" #if defined(OF_HAVE_PTHREADS) -# include "platform/posix/OFPlainThread.m" +# include "platform/POSIX/OFPlainThread.m" #elif defined(OF_WINDOWS) -# include "platform/windows/OFPlainThread.m" +# include "platform/Windows/OFPlainThread.m" #elif defined(OF_AMIGAOS) -# include "platform/amiga/OFPlainThread.m" +# include "platform/AmigaOS/OFPlainThread.m" #endif Index: src/OFRunLoop.m ================================================================== --- src/OFRunLoop.m +++ src/OFRunLoop.m @@ -41,11 +41,12 @@ #import "OFTimer+Private.h" #import "OFDate.h" #import "OFObserveFailedException.h" -const OFRunLoopMode OFDefaultRunLoopMode = @"OFDefaultRunLoopMode"; +#include "OFRunLoopConstants.inc" + static OFRunLoop *mainRunLoop = nil; @interface OFRunLoopState: OFObject #ifdef OF_HAVE_SOCKETS ADDED src/OFRunLoopConstants.inc Index: src/OFRunLoopConstants.inc ================================================================== --- src/OFRunLoopConstants.inc +++ src/OFRunLoopConstants.inc @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2008-2021 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +const OFRunLoopMode OFDefaultRunLoopMode = @"OFDefaultRunLoopMode"; Index: src/OFSPXSocket.m ================================================================== --- src/OFSPXSocket.m +++ src/OFSPXSocket.m @@ -115,11 +115,15 @@ } _socket.canBlock = false; if (![_socket of_connectSocketToAddress: &address errNo: &errNo]) { +#ifdef OF_WINDOWS + if (errNo == EINPROGRESS || errNo == EWOULDBLOCK) { +#else if (errNo == EINPROGRESS) { +#endif [OFRunLoop of_addAsyncConnectForSocket: _socket mode: runLoopMode delegate: self]; return; } Index: src/OFSPXStreamSocket.m ================================================================== --- src/OFSPXStreamSocket.m +++ src/OFSPXStreamSocket.m @@ -116,11 +116,15 @@ } _socket.canBlock = false; if (![_socket of_connectSocketToAddress: &address errNo: &errNo]) { +#ifdef OF_WINDOWS + if (errNo == EINPROGRESS || errNo == EWOULDBLOCK) { +#else if (errNo == EINPROGRESS) { +#endif [OFRunLoop of_addAsyncConnectForSocket: _socket mode: runLoopMode delegate: self]; return; } Index: src/OFSecureData.h ================================================================== --- src/OFSecureData.h +++ src/OFSecureData.h @@ -30,11 +30,11 @@ * memory. */ OF_SUBCLASSING_RESTRICTED @interface OFSecureData: OFData { - struct page *_page; + void *_page; bool _allowsSwappableMemory; } /** * @brief Whether the data may be stored in swappable memory. Index: src/OFSecureData.m ================================================================== --- src/OFSecureData.m +++ src/OFSecureData.m @@ -36,28 +36,28 @@ #import "OFOutOfRangeException.h" #if defined(HAVE_MMAP) && defined(HAVE_MLOCK) && defined(MAP_ANON) static const size_t chunkSize = 16; -struct page { - struct page *next, *previous; +struct Page { + struct Page *next, *previous; void *map; unsigned char *page; }; # if defined(OF_HAVE_COMPILER_TLS) -static thread_local struct page *firstPage = NULL; -static thread_local struct page *lastPage = NULL; -static thread_local struct page **preallocatedPages = NULL; +static thread_local struct Page *firstPage = NULL; +static thread_local struct Page *lastPage = NULL; +static thread_local struct Page **preallocatedPages = NULL; static thread_local size_t numPreallocatedPages = 0; # elif defined(OF_HAVE_THREADS) static OFTLSKey firstPageKey, lastPageKey; static OFTLSKey preallocatedPagesKey, numPreallocatedPagesKey; # else -static struct page *firstPage = NULL; -static struct page *lastPage = NULL; -static struct page **preallocatedPages = NULL; +static struct Page *firstPage = NULL; +static struct Page *lastPage = NULL; +static struct Page **preallocatedPages = NULL; static size_t numPreallocatedPages = 0; # endif static void * mapPages(size_t numPages) @@ -92,19 +92,19 @@ munlock(pointer, numPages * pageSize); munmap(pointer, numPages * pageSize); } -static struct page * +static struct Page * addPage(bool allowPreallocated) { size_t pageSize = [OFSystemInfo pageSize]; size_t mapSize = OFRoundUpToPowerOf2(CHAR_BIT, pageSize / chunkSize) / CHAR_BIT; - struct page *page; + struct Page *page; # if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) - struct page *lastPage; + struct Page *lastPage; # endif if (allowPreallocated) { # if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) uintptr_t numPreallocatedPages = @@ -111,11 +111,11 @@ (uintptr_t)OFTLSKeyGet(numPreallocatedPagesKey); # endif if (numPreallocatedPages > 0) { # if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) - struct page **preallocatedPages = + struct Page **preallocatedPages = OFTLSKeyGet(preallocatedPagesKey); # endif numPreallocatedPages--; # if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) @@ -178,11 +178,11 @@ return page; } static void -removePageIfEmpty(struct page *page) +removePageIfEmpty(struct Page *page) { unsigned char *map = page->map; size_t pageSize = [OFSystemInfo pageSize]; size_t mapSize = OFRoundUpToPowerOf2(CHAR_BIT, pageSize / chunkSize) / CHAR_BIT; @@ -213,11 +213,11 @@ OFFreeMemory(page); } static void * -allocateMemory(struct page *page, size_t bytes) +allocateMemory(struct Page *page, size_t bytes) { size_t chunks, chunksLeft, pageSize, i, firstChunk; bytes = OFRoundUpToPowerOf2(chunkSize, bytes); chunks = chunksLeft = bytes / chunkSize; @@ -244,11 +244,11 @@ return NULL; } static void -freeMemory(struct page *page, void *pointer, size_t bytes) +freeMemory(struct Page *page, void *pointer, size_t bytes) { size_t chunks, chunkIndex; bytes = OFRoundUpToPowerOf2(chunkSize, bytes); chunks = bytes / chunkSize; @@ -283,19 +283,19 @@ { #if defined(HAVE_MMAP) && defined(HAVE_MLOCK) && defined(MAP_ANON) size_t pageSize = [OFSystemInfo pageSize]; size_t numPages = OFRoundUpToPowerOf2(pageSize, size) / pageSize; # if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) - struct page **preallocatedPages = OFTLSKeyGet(preallocatedPagesKey); + struct Page **preallocatedPages = OFTLSKeyGet(preallocatedPagesKey); size_t numPreallocatedPages; # endif size_t i; if (preallocatedPages != NULL) @throw [OFInvalidArgumentException exception]; - preallocatedPages = OFAllocZeroedMemory(numPages, sizeof(struct page)); + preallocatedPages = OFAllocZeroedMemory(numPages, sizeof(struct Page)); # if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) OFEnsure(OFTLSKeySet(preallocatedPagesKey, preallocatedPages) == 0); # endif @try { @@ -421,14 +421,14 @@ } else if (count * itemSize >= pageSize) _items = mapPages(OFRoundUpToPowerOf2(pageSize, count * itemSize) / pageSize); else { # if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) - struct page *lastPage = OFTLSKeyGet(lastPageKey); + struct Page *lastPage = OFTLSKeyGet(lastPageKey); # endif - for (struct page *page = lastPage; page != NULL; + for (struct Page *page = lastPage; page != NULL; page = page->previous) { _items = allocateMemory(page, count * itemSize); if (_items != NULL) { _page = page; Index: src/OFSequencedPacketSocket.m ================================================================== --- src/OFSequencedPacketSocket.m +++ src/OFSequencedPacketSocket.m @@ -133,11 +133,11 @@ @throw [OFSetOptionFailedException exceptionWithObject: self errNo: errno]; _canBlock = canBlock; #elif defined(OF_WINDOWS) - u_long v = canBlock; + u_long v = !canBlock; if (ioctlsocket(_socket, FIONBIO, &v) == SOCKET_ERROR) @throw [OFSetOptionFailedException exceptionWithObject: self errNo: OFSocketErrNo()]; Index: src/OFStdIOStream.h ================================================================== --- src/OFStdIOStream.h +++ src/OFStdIOStream.h @@ -148,16 +148,27 @@ * @brief The standard error as an OFStream. */ extern OFStdIOStream *_Nullable OFStdErr; /** - * @brief Log the specified printf-style format to @ref OFStdErr. + * @brief Logs the specified printf-style format to @ref OFStdErr. + * + * This prefixes the output with the date, timestamp, process name and PID. * - * This prefixes the output with the date, timestamp, process name and PID and - * allows `%@` as a printf-style formatted to print objects. + * @param format The format for the line to log. See @ref OFStream#writeFormat:. */ extern void OFLog(OFConstantString *format, ...); + +/** + * @brief Logs the specified printf-style format to @ref OFStdErr. + * + * This prefixes the output with the date, timestamp, process name and PID. + * + * @param format The format for the line to log. See @ref OFStream#writeFormat:. + * @param arguments The arguments for the format + */ +extern void OFLogV(OFConstantString *format, va_list arguments); #ifdef __cplusplus } #endif OF_ASSUME_NONNULL_END Index: src/OFStdIOStream.m ================================================================== --- src/OFStdIOStream.m +++ src/OFStdIOStream.m @@ -75,27 +75,34 @@ #endif void OFLog(OFConstantString *format, ...) { + va_list arguments; + + va_start(arguments, format); + OFLogV(format, arguments); + va_end(arguments); +} + +void +OFLogV(OFConstantString *format, va_list arguments) +{ void *pool = objc_autoreleasePoolPush(); OFDate *date; OFString *dateString, *me, *msg; - va_list arguments; date = [OFDate date]; dateString = [date localDateStringWithFormat: @"%Y-%m-%d %H:%M:%S"]; #ifdef OF_HAVE_FILES me = [OFApplication programName].lastPathComponent; #else me = [OFApplication programName]; #endif - va_start(arguments, format); msg = [[[OFString alloc] initWithFormat: format arguments: arguments] autorelease]; - va_end(arguments); [OFStdErr writeFormat: @"[%@.%03d %@(%d)] %@\n", dateString, date.microsecond / 1000, me, getpid(), msg]; objc_autoreleasePoolPop(pool); Index: src/OFStrPTime.h ================================================================== --- src/OFStrPTime.h +++ src/OFStrPTime.h @@ -27,12 +27,12 @@ OF_ASSUME_NONNULL_BEGIN #ifdef __cplusplus extern "C" { #endif -extern const char *OFStrPTime(const char *buf, const char *fmt, struct tm *tm, - short *tz); +extern const char *_Nullable OFStrPTime(const char *buffer, const char *format, + struct tm *tm, short *_Nullable tz); #ifdef __cplusplus } #endif OF_ASSUME_NONNULL_END Index: src/OFStream.h ================================================================== --- src/OFStream.h +++ src/OFStream.h @@ -205,11 +205,11 @@ @property (readonly, nonatomic, getter=isAtEndOfStream) bool atEndOfStream; /** * @brief Whether writes are buffered. */ -@property (nonatomic, nonatomic) bool buffersWrites; +@property (nonatomic) bool buffersWrites; /** * @brief Whether data is present in the internal read buffer. */ @property (readonly, nonatomic) bool hasDataInReadBuffer; Index: src/OFStreamSocket.m ================================================================== --- src/OFStreamSocket.m +++ src/OFStreamSocket.m @@ -162,13 +162,13 @@ #if defined(OF_WINDOWS) || defined(OF_AMIGAOS) - (void)setCanBlock: (bool)canBlock { # ifdef OF_WINDOWS - u_long v = canBlock; + u_long v = !canBlock; # else - char v = canBlock; + char v = !canBlock; # endif if (ioctlsocket(_socket, FIONBIO, &v) == SOCKET_ERROR) @throw [OFSetOptionFailedException exceptionWithObject: self Index: src/OFString+PathAdditions.m ================================================================== --- src/OFString+PathAdditions.m +++ src/OFString+PathAdditions.m @@ -16,13 +16,13 @@ #include "config.h" #include "platform.h" #if defined(OF_WINDOWS) || defined(OF_MSDOS) -# import "platform/windows/OFString+PathAdditions.m" +# import "platform/Windows/OFString+PathAdditions.m" #elif defined(OF_AMIGAOS) -# import "platform/amiga/OFString+PathAdditions.m" +# import "platform/AmigaOS/OFString+PathAdditions.m" #elif defined(OF_NINTENDO_3DS) || defined(OF_WII) # import "platform/libfat/OFString+PathAdditions.m" #else -# import "platform/posix/OFString+PathAdditions.m" +# import "platform/POSIX/OFString+PathAdditions.m" #endif Index: src/OFString+URLEncoding.m ================================================================== --- src/OFString+URLEncoding.m +++ src/OFString+URLEncoding.m @@ -82,10 +82,11 @@ size_t length = self.UTF8StringLength; char *retCString; char byte = 0; int state = 0; size_t i = 0; + OFString *ret; retCString = OFAllocMemory(length + 1, 1); while (length--) { char c = *string++; @@ -135,14 +136,16 @@ } @catch (OFOutOfMemoryException *e) { /* We don't care if it fails, as we only made it smaller. */ } @try { - return [OFString stringWithUTF8StringNoCopy: retCString - length: i - freeWhenDone: true]; + ret = [OFString stringWithUTF8StringNoCopy: retCString + length: i + freeWhenDone: true]; } @catch (id e) { OFFreeMemory(retCString); @throw e; } + + return ret; } @end Index: src/OFString.h ================================================================== --- src/OFString.h +++ src/OFString.h @@ -324,12 +324,12 @@ /** * @brief Creates a new OFString from a UTF-8 encoded C string without copying * the string, if possible. * - * If initialization fails for whatever reason, the passed C string is free'd - * if `freeWhenDone` is true. + * If initialization fails for whatever reason, the passed C string is *not* + * free'd if `freeWhenDone` is true. * * @note OFMutableString always creates a copy! * * @param UTF8String A UTF-8 encoded C string to initialize the OFString with * @param freeWhenDone Whether to free the C string when the OFString gets @@ -341,12 +341,12 @@ /** * @brief Creates a new OFString from a UTF-8 encoded C string with the * specified length without copying the string, if possible. * - * If initialization fails for whatever reason, the passed C string is free'd - * if `freeWhenDone` is true. + * If initialization fails for whatever reason, the passed C string is *not* + * free'd if `freeWhenDone` is true. * * @note OFMutableString always creates a copy! * * @param UTF8String A UTF-8 encoded C string to initialize the OFString with * @param UTF8StringLength The length of the UTF-8 encoded C string @@ -579,12 +579,12 @@ /** * @brief Initializes an already allocated OFString from an UTF-8 encoded C * string without copying the string, if possible. * - * If initialization fails for whatever reason, the passed C string is free'd - * if `freeWhenDone` is true. + * If initialization fails for whatever reason, the passed C string is *not* + * free'd if `freeWhenDone` is true. * * @note OFMutableString always creates a copy! * * @param UTF8String A UTF-8 encoded C string to initialize the OFString with * @param freeWhenDone Whether to free the C string when it is not needed @@ -597,12 +597,12 @@ /** * @brief Initializes an already allocated OFString from an UTF-8 encoded C * string with the specified length without copying the string, if * possible. * - * If initialization fails for whatever reason, the passed C string is free'd - * if `freeWhenDone` is true. + * If initialization fails for whatever reason, the passed C string is *not* + * free'd if `freeWhenDone` is true. * * @note OFMutableString always creates a copy! * * @param UTF8String A UTF-8 encoded C string to initialize the OFString with * @param UTF8StringLength The length of the UTF-8 encoded C string Index: src/OFString.m ================================================================== --- src/OFString.m +++ src/OFString.m @@ -1378,10 +1378,11 @@ lossy: (bool)lossy { size_t length = self.length; char *cString; size_t cStringLength; + const char *ret; switch (encoding) { case OFStringEncodingUTF8: cString = OFAllocMemory((length * 4) + 1, 1); @@ -1432,17 +1433,19 @@ default: @throw [OFInvalidEncodingException exception]; } @try { - return [[OFData dataWithItemsNoCopy: cString - count: cStringLength + 1 - freeWhenDone: true] items]; + ret = [[OFData dataWithItemsNoCopy: cString + count: cStringLength + 1 + freeWhenDone: true] items]; } @catch (id e) { OFFreeMemory(cString); @throw e; } + + return ret; } - (const char *)cStringWithEncoding: (OFStringEncoding)encoding { return [self of_cStringWithEncoding: encoding lossy: false]; @@ -2537,23 +2540,26 @@ - (const OFUnichar *)characters { size_t length = self.length; OFUnichar *buffer; + const OFUnichar *ret; buffer = OFAllocMemory(length, sizeof(OFUnichar)); @try { [self getCharacters: buffer inRange: OFRangeMake(0, length)]; - return [[OFData dataWithItemsNoCopy: buffer - count: length - itemSize: sizeof(OFUnichar) - freeWhenDone: true] items]; + ret = [[OFData dataWithItemsNoCopy: buffer + count: length + itemSize: sizeof(OFUnichar) + freeWhenDone: true] items]; } @catch (id e) { OFFreeMemory(buffer); @throw e; } + + return ret; } - (const OFChar16 *)UTF16String { return [self UTF16StringWithByteOrder: OFByteOrderNative]; @@ -2565,10 +2571,11 @@ const OFUnichar *characters = self.characters; size_t length = self.length; OFChar16 *buffer; size_t j; bool swap = (byteOrder != OFByteOrderNative); + const OFChar16 *ret; /* Allocate memory for the worst case */ buffer = OFAllocMemory((length + 1) * 2, sizeof(OFChar16)); j = 0; @@ -2606,18 +2613,20 @@ } objc_autoreleasePoolPop(pool); @try { - return [[OFData dataWithItemsNoCopy: buffer - count: j + 1 - itemSize: sizeof(OFChar16) - freeWhenDone: true] items]; + ret = [[OFData dataWithItemsNoCopy: buffer + count: j + 1 + itemSize: sizeof(OFChar16) + freeWhenDone: true] items]; } @catch (id e) { OFFreeMemory(buffer); @throw e; } + + return ret; } - (size_t)UTF16StringLength { const OFUnichar *characters = self.characters; @@ -2639,10 +2648,11 @@ - (const OFChar32 *)UTF32StringWithByteOrder: (OFByteOrder)byteOrder { size_t length = self.length; OFChar32 *buffer; + const OFChar32 *ret; buffer = OFAllocMemory(length + 1, sizeof(OFChar32)); @try { [self getCharacters: buffer inRange: OFRangeMake(0, length)]; buffer[length] = 0; @@ -2649,18 +2659,20 @@ if (byteOrder != OFByteOrderNative) for (size_t i = 0; i < length; i++) buffer[i] = OFByteSwap32(buffer[i]); - return [[OFData dataWithItemsNoCopy: buffer - count: length + 1 - itemSize: sizeof(OFChar32) - freeWhenDone: true] items]; + ret = [[OFData dataWithItemsNoCopy: buffer + count: length + 1 + itemSize: sizeof(OFChar32) + freeWhenDone: true] items]; } @catch (id e) { OFFreeMemory(buffer); @throw e; } + + return ret; } - (OFData *)dataWithEncoding: (OFStringEncoding)encoding { void *pool = objc_autoreleasePoolPush(); Index: src/OFSubprocess.m ================================================================== --- src/OFSubprocess.m +++ src/OFSubprocess.m @@ -16,9 +16,9 @@ #include "config.h" #include "platform.h" #ifdef OF_WINDOWS -# include "platform/windows/OFSubprocess.m" +# include "platform/Windows/OFSubprocess.m" #else -# include "platform/posix/OFSubprocess.m" +# include "platform/POSIX/OFSubprocess.m" #endif Index: src/OFSystemInfo.h ================================================================== --- src/OFSystemInfo.h +++ src/OFSystemInfo.h @@ -116,32 +116,52 @@ #ifdef OF_HAVE_FILES /** * @brief Returns the path where user data for the application can be stored. * - * On Unix systems, this adheres to the XDG Base Directory specification.@n - * On Mac OS X and iOS, it uses the `NSApplicationSupportDirectory` directory.@n + * On UNIX systems, this adheres to the XDG Base Directory specification.@n + * On macOS and iOS, it uses the `NSApplicationSupportDirectory` directory.@n * On Windows, it uses the `APPDATA` environment variable.@n - * On Haiku, it uses the `B_USER_SETTINGS_DIRECTORY` directory. + * On Haiku, it uses the `B_USER_SETTINGS_DIRECTORY` directory.@n + * On AmigaOS and MorphOS, it returns `PROGDIR:`. * * @return The path where user data for the application can be stored */ + (nullable OFString *)userDataPath; /** * @brief Returns the path where user configuration for the application can be * stored. * - * On Unix systems, this adheres to the XDG Base Directory specification.@n - * On Mac OS X and iOS, it uses the `Preferences` directory inside of + * On UNIX systems, this adheres to the XDG Base Directory specification.@n + * On macOS and iOS, it uses the `Preferences` directory inside of * `NSLibraryDirectory` directory.@n * On Windows, it uses the `APPDATA` environment variable.@n * On Haiku, it uses the `B_USER_SETTINGS_DIRECTORY` directory. + * On AmigaOS and MorphOS, it returns `PROGDIR:`. * * @return The path where user configuration for the application can be stored */ + (nullable OFString *)userConfigPath; + +/** + * @brief Returns a path where temporary files for can be stored. + * + * If possible, returns a temporary directory for the user, otherwise returns a + * global temporary directory. + * + * On UNIX systems, this adheres to the XDG Base Directory specification and + * returns `/tmp` if `XDG_RUNTIME_DIR` is not set.@n + * On macOS and iOS, this uses `_CS_DARWIN_USER_TEMP_DIR`, falling back to + * `/tmp` if this fails.@n + * On Windows, it uses `GetTempPath`.@n + * On Haiku, it uses the `B_SYSTEM_TEMP_DIRECTORY` directory. + * On AmigaOS and MorphOS, it returns `T:`. + * + * @return A path where temporary files can be stored + */ ++ (nullable OFString *)temporaryDirectoryPath; #endif /** * @brief Returns the vendor of the CPU. * Index: src/OFSystemInfo.m ================================================================== --- src/OFSystemInfo.m +++ src/OFSystemInfo.m @@ -352,12 +352,11 @@ # if defined(OF_MACOS) || defined(OF_IOS) char pathC[PATH_MAX]; OFMutableString *path; # ifdef HAVE_SYSDIR_START_SEARCH_PATH_ENUMERATION - /* (1) to disable dead code warning when it is not a weak symbol */ - if ((1) && &sysdir_start_search_path_enumeration != NULL) { + if (@available(macOS 10.12, iOS 10, *)) { sysdir_search_path_enumeration_state state; state = sysdir_start_search_path_enumeration( SYSDIR_DIRECTORY_APPLICATION_SUPPORT, SYSDIR_DOMAIN_MASK_USER); @@ -445,12 +444,11 @@ # if defined(OF_MACOS) || defined(OF_IOS) char pathC[PATH_MAX]; OFMutableString *path; # ifdef HAVE_SYSDIR_START_SEARCH_PATH_ENUMERATION - /* (1) to disable dead code warning when it is not a weak symbol */ - if ((1) && &sysdir_start_search_path_enumeration != NULL) { + if (@available(macOS 10.12, iOS 10, *)) { sysdir_search_path_enumeration_state state; state = sysdir_start_search_path_enumeration( SYSDIR_DIRECTORY_LIBRARY, SYSDIR_DOMAIN_MASK_USER); if (sysdir_get_next_search_path_enumeration(state, pathC) == 0) @@ -522,10 +520,61 @@ object: self]; return [var stringByAppendingPathComponent: @".config"]; # endif } + ++ (OFString *)temporaryDirectoryPath +{ +# if defined(OF_MACOS) || defined(OF_IOS) + char buffer[PATH_MAX]; + size_t length; + + if ((length = confstr(_CS_DARWIN_USER_TEMP_DIR, buffer, PATH_MAX)) == 0) + return @"/tmp"; + + return [OFString stringWithCString: buffer + encoding: [OFLocale encoding] + length: length - 1]; +# elif defined(OF_WINDOWS) + if ([self isWindowsNT]) { + wchar_t buffer[PATH_MAX]; + + if (!GetTempPathW(PATH_MAX, buffer)) + return nil; + + return [OFString stringWithUTF16String: buffer]; + } else { + char buffer[PATH_MAX]; + + if (!GetTempPathA(PATH_MAX, buffer)) + return nil; + + return [OFString stringWithCString: buffer + encoding: [OFLocale encoding]]; + } +# elif defined(OF_HAIKU) + char pathC[PATH_MAX]; + + if (find_directory(B_SYSTEM_TEMP_DIRECTORY, 0, false, + pathC, PATH_MAX) != B_OK) + @throw [OFNotImplementedException exceptionWithSelector: _cmd + object: self]; + + return [OFString stringWithUTF8String: pathC]; +# elif defined(OF_AMIGAOS) + return @"T:"; +# else + OFString *path = + [[OFApplication environment] objectForKey: @"XDG_RUNTIME_DIR"]; + + if (path != nil) + return path; + + return @"/tmp"; +# endif +} #endif + (OFString *)CPUVendor { #if (defined(OF_X86_64) || defined(OF_X86)) && defined(__GNUC__) Index: src/OFTLSKey.m ================================================================== --- src/OFTLSKey.m +++ src/OFTLSKey.m @@ -16,13 +16,13 @@ #include "config.h" #include "platform.h" #if defined(OF_HAVE_PTHREADS) -# include "platform/posix/OFTLSKey.m" +# include "platform/POSIX/OFTLSKey.m" #elif defined(OF_WINDOWS) -# include "platform/windows/OFTLSKey.m" +# include "platform/Windows/OFTLSKey.m" #elif defined(OF_MORPHOS) -# include "platform/morphos/OFTLSKey.m" +# include "platform/MorphOS/OFTLSKey.m" #elif defined(OF_AMIGAOS) -# include "platform/amiga/OFTLSKey.m" +# include "platform/AmigaOS/OFTLSKey.m" #endif Index: src/OFTimer.h ================================================================== --- src/OFTimer.h +++ src/OFTimer.h @@ -67,13 +67,13 @@ * repeating timer. */ @property (readonly, nonatomic) OFTimeInterval timeInterval; /** - * @brief Whether the timer is repeating. + * @brief Whether the timer repeats. */ -@property (readonly, nonatomic, getter=isRepeating) bool repeating; +@property (readonly, nonatomic) bool repeats; /** * @brief Whether the timer is valid. */ @property (readonly, nonatomic, getter=isValid) bool valid; Index: src/OFTimer.m ================================================================== --- src/OFTimer.m +++ src/OFTimer.m @@ -29,11 +29,11 @@ #endif #import "OFInvalidArgumentException.h" @implementation OFTimer -@synthesize timeInterval = _interval, repeating = _repeats, valid = _valid; +@synthesize timeInterval = _interval, repeats = _repeats, valid = _valid; + (instancetype)scheduledTimerWithTimeInterval: (OFTimeInterval)timeInterval target: (id)target selector: (SEL)selector repeats: (bool)repeats @@ -664,6 +664,35 @@ } @finally { [_condition unlock]; } } #endif + +- (OFString *)description +{ +#ifdef OF_HAVE_BLOCKS + if (_block != NULL) + return [OFString stringWithFormat: + @"<%@:\n" + @"\tFire date: %@\n" + @"\tInterval: %lf\n" + @"\tRepeats: %s\n" + @"\tBlock: %@\n" + @"\tValid: %s\n" + @">", + self.class, _fireDate, _interval, (_repeats ? "yes" : "no"), + _block, (_valid ? "yes" : "no")]; + else +#endif + return [OFString stringWithFormat: + @"<%@:\n" + @"\tFire date: %@\n" + @"\tInterval: %lf\n" + @"\tRepeats: %s\n" + @"\tTarget: %@\n" + @"\tSelector: %s\n" + @"\tValid: %s\n" + @">", + self.class, _fireDate, _interval, (_repeats ? "yes" : "no"), + _target, sel_getName(_selector), (_valid ? "yes" : "no")]; +} @end Index: src/OFUTF8String.m ================================================================== --- src/OFUTF8String.m +++ src/OFUTF8String.m @@ -1155,10 +1155,11 @@ - (const OFUnichar *)characters { OFUnichar *buffer = OFAllocMemory(_s->length, sizeof(OFUnichar)); size_t i = 0, j = 0; + const OFUnichar *ret; while (i < _s->cStringLength) { OFUnichar c; ssize_t cLen; @@ -1172,20 +1173,28 @@ buffer[j++] = c; i += cLen; } - return [[OFData dataWithItemsNoCopy: buffer - count: _s->length - itemSize: sizeof(OFUnichar) - freeWhenDone: true] items]; + @try { + ret = [[OFData dataWithItemsNoCopy: buffer + count: _s->length + itemSize: sizeof(OFUnichar) + freeWhenDone: true] items]; + } @catch (id e) { + OFFreeMemory(buffer); + @throw e; + } + + return ret; } - (const OFChar32 *)UTF32StringWithByteOrder: (OFByteOrder)byteOrder { OFChar32 *buffer = OFAllocMemory(_s->length + 1, sizeof(OFChar32)); size_t i = 0, j = 0; + const OFChar32 *ret; while (i < _s->cStringLength) { OFChar32 c; ssize_t cLen; @@ -1204,14 +1213,21 @@ i += cLen; } buffer[j] = 0; - return [[OFData dataWithItemsNoCopy: buffer - count: _s->length + 1 - itemSize: sizeof(OFChar32) - freeWhenDone: true] items]; + @try { + ret = [[OFData dataWithItemsNoCopy: buffer + count: _s->length + 1 + itemSize: sizeof(OFChar32) + freeWhenDone: true] items]; + } @catch (id e) { + OFFreeMemory(buffer); + @throw e; + } + + return ret; } #ifdef OF_HAVE_BLOCKS - (void)enumerateLinesUsingBlock: (OFStringLineEnumerationBlock)block { Index: src/macros.h ================================================================== --- src/macros.h +++ src/macros.h @@ -607,15 +607,15 @@ #ifdef OF_FLOAT_BIG_ENDIAN # define OFFromBigEndianFloat(f) (f) # define OFFromBigEndianDouble(d) (d) # define OFFromLittleEndianFloat(f) OFByteSwapFloat(f) -# define OFFromLittleEndianDouble(i) OFByteSwapDouble(d) +# define OFFromLittleEndianDouble(d) OFByteSwapDouble(d) # define OFToBigEndianFloat(f) (f) # define OFToBigEndianDouble(d) (d) # define OFToLittleEndianFloat(f) OFByteSwapFloat(f) -# define OFToLittleEndianDouble(i) OFByteSwapDouble(d) +# define OFToLittleEndianDouble(d) OFByteSwapDouble(d) #else # define OFFromBigEndianFloat(f) OFByteSwapFloat(f) # define OFFromBigEndianDouble(d) OFByteSwapDouble(d) # define OFFromLittleEndianFloat(f) (f) # define OFFromLittleEndianDouble(d) (d) Index: src/module.modulemap ================================================================== --- src/module.modulemap +++ src/module.modulemap @@ -3,14 +3,13 @@ /* * These are included by OFAtomic.h, but should never be included * directly. */ - exclude header "OFAtomic_builtins.h" - exclude header "OFAtomic_no_threads.h" - exclude header "OFAtomic_osatomic.h" - exclude header "OFAtomic_powerpc.h" - exclude header "OFAtomic_sync_builtins.h" - exclude header "OFAtomic_x86.h" + exclude header "platform/GCC4/OFAtomic.h" + exclude header "platform/GCC4.7/OFAtomic.h" + exclude header "platform/PowerPC/OFAtomic.h" + exclude header "platform/macOS/OFAtomic.h" + exclude header "platform/x86/OFAtomic.h" export * } ADDED src/platform/AmigaOS/OFPlainCondition.m Index: src/platform/AmigaOS/OFPlainCondition.m ================================================================== --- src/platform/AmigaOS/OFPlainCondition.m +++ src/platform/AmigaOS/OFPlainCondition.m @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2008-2021 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#include + +#import "OFPlainCondition.h" + +#include +#include +#ifndef OF_AMIGAOS4 +# include +#endif + +int +OFPlainConditionNew(OFPlainCondition *condition) +{ + condition->waitingTasks = NULL; + + return 0; +} + +int +OFPlainConditionSignal(OFPlainCondition *condition) +{ + Forbid(); + @try { + if (condition->waitingTasks == NULL) + return 0; + + Signal(condition->waitingTasks->task, + (1ul << condition->waitingTasks->sigBit)); + + condition->waitingTasks = condition->waitingTasks->next; + } @finally { + Permit(); + } + + return 0; +} + +int +OFPlainConditionBroadcast(OFPlainCondition *condition) +{ + Forbid(); + @try { + if (condition->waitingTasks == NULL) + return 0; + + while (condition->waitingTasks != NULL) { + Signal(condition->waitingTasks->task, + (1ul << condition->waitingTasks->sigBit)); + + condition->waitingTasks = condition->waitingTasks->next; + } + } @finally { + Permit(); + } + + return 0; +} + +int +OFPlainConditionWait(OFPlainCondition *condition, OFPlainMutex *mutex) +{ + ULONG signalMask = 0; + + return OFPlainConditionWaitOrExecSignal(condition, mutex, &signalMask); +} + +int +OFPlainConditionWaitOrExecSignal(OFPlainCondition *condition, + OFPlainMutex *mutex, ULONG *signalMask) +{ + struct OFPlainConditionWaitingTask waitingTask = { + .task = FindTask(NULL), + .sigBit = AllocSignal(-1) + }; + int error = 0; + ULONG mask; + + if (waitingTask.sigBit == -1) + return EAGAIN; + + Forbid(); + + if ((error = OFPlainMutexUnlock(mutex)) != 0) { + FreeSignal(waitingTask.sigBit); + return error; + } + + waitingTask.next = condition->waitingTasks; + condition->waitingTasks = &waitingTask; + + mask = Wait((1ul << waitingTask.sigBit) | *signalMask); + if (mask & (1ul << waitingTask.sigBit) || (*signalMask &= mask)) + error = OFPlainMutexLock(mutex); + else + /* + * This should not happen - it means something interrupted the + * Wait(), so the best we can do is return EINTR. + */ + error = EINTR; + + FreeSignal(waitingTask.sigBit); + + Permit(); + + return error; +} + +int +OFPlainConditionTimedWait(OFPlainCondition *condition, OFPlainMutex *mutex, + OFTimeInterval timeout) +{ + ULONG signalMask = 0; + + return OFPlainConditionTimedWaitOrExecSignal(condition, mutex, timeout, + &signalMask); +} + +int +OFPlainConditionTimedWaitOrExecSignal(OFPlainCondition *condition, + OFPlainMutex *mutex, OFTimeInterval timeout, ULONG *signalMask) +{ + struct OFPlainConditionWaitingTask waitingTask = { + .task = FindTask(NULL), + .sigBit = AllocSignal(-1) + }; + struct MsgPort port = { + .mp_Node = { + .ln_Type = NT_MSGPORT + }, + .mp_Flags = PA_SIGNAL, + .mp_SigTask = waitingTask.task, + .mp_SigBit = AllocSignal(-1) + }; +#ifdef OF_AMIGAOS4 + struct TimeRequest request = { + .Request = { +#else + struct timerequest request = { + .tr_node = { +#endif + .io_Message = { + .mn_Node = { + .ln_Type = NT_MESSAGE + }, + .mn_ReplyPort = &port, + .mn_Length = sizeof(request) + }, + .io_Command = TR_ADDREQUEST + }, +#ifdef OF_AMIGAOS4 + .Time = { + .Seconds = (ULONG)timeout, + .Microseconds = + (timeout - request.Time.Seconds) * 1000000 +#else + .tr_time = { + .tv_sec = (ULONG)timeout, + .tv_micro = (timeout - request.tr_time.tv_sec) * 1000000 +#endif + } + }; + int error = 0; + ULONG mask; + + NewList(&port.mp_MsgList); + + if (waitingTask.sigBit == -1 || port.mp_SigBit == -1) { + error = EAGAIN; + goto fail; + } + + if (OpenDevice("timer.device", UNIT_MICROHZ, + (struct IORequest *)&request, 0) != 0) { + error = EAGAIN; + goto fail; + } + + Forbid(); + + if ((error = OFPlainMutexUnlock(mutex)) != 0) { + Permit(); + goto fail; + } + + waitingTask.next = condition->waitingTasks; + condition->waitingTasks = &waitingTask; + + SendIO((struct IORequest *)&request); + + mask = Wait((1ul << waitingTask.sigBit) | (1ul << port.mp_SigBit) | + *signalMask); + if (mask & (1ul << waitingTask.sigBit) || (*signalMask &= mask)) + error = OFPlainMutexLock(mutex); + else if (mask & (1ul << port.mp_SigBit)) + error = ETIMEDOUT; + else + /* + * This should not happen - it means something interrupted the + * Wait(), so the best we can do is return EINTR. + */ + error = EINTR; + + condition->waitingTasks = waitingTask.next; + + if (!CheckIO((struct IORequest *)&request)) { + AbortIO((struct IORequest *)&request); + WaitIO((struct IORequest *)&request); + } + CloseDevice((struct IORequest *)&request); + + Permit(); + +fail: + if (waitingTask.sigBit != -1) + FreeSignal(waitingTask.sigBit); + if (port.mp_SigBit != -1) + FreeSignal(port.mp_SigBit); + + return error; +} + +int +OFPlainConditionFree(OFPlainCondition *condition) +{ + Forbid(); + @try { + if (condition->waitingTasks != NULL) + return EBUSY; + } @finally { + Permit(); + } + + return 0; +} ADDED src/platform/AmigaOS/OFPlainMutex.m Index: src/platform/AmigaOS/OFPlainMutex.m ================================================================== --- src/platform/AmigaOS/OFPlainMutex.m +++ src/platform/AmigaOS/OFPlainMutex.m @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2008-2021 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#include + +#import "OFPlainMutex.h" + +#include + +int +OFPlainMutexNew(OFPlainMutex *mutex) +{ + InitSemaphore(mutex); + + return 0; +} + +int +OFPlainMutexLock(OFPlainMutex *mutex) +{ + ObtainSemaphore(mutex); + + return 0; +} + +int +OFPlainMutexTryLock(OFPlainMutex *mutex) +{ + if (!AttemptSemaphore(mutex)) + return EBUSY; + + return 0; +} + +int +OFPlainMutexUnlock(OFPlainMutex *mutex) +{ + ReleaseSemaphore(mutex); + + return 0; +} + +int +OFPlainMutexFree(OFPlainMutex *mutex) +{ + return 0; +} + +int +OFPlainRecursiveMutexNew(OFPlainRecursiveMutex *rmutex) +{ + return OFPlainMutexNew(rmutex); +} + +int +OFPlainRecursiveMutexLock(OFPlainRecursiveMutex *rmutex) +{ + return OFPlainMutexLock(rmutex); +} + +int +OFPlainRecursiveMutexTryLock(OFPlainRecursiveMutex *rmutex) +{ + return OFPlainMutexTryLock(rmutex); +} + +int +OFPlainRecursiveMutexUnlock(OFPlainRecursiveMutex *rmutex) +{ + return OFPlainMutexUnlock(rmutex); +} + +int +OFPlainRecursiveMutexFree(OFPlainRecursiveMutex *rmutex) +{ + return OFPlainMutexFree(rmutex); +} ADDED src/platform/AmigaOS/OFPlainThread.m Index: src/platform/AmigaOS/OFPlainThread.m ================================================================== --- src/platform/AmigaOS/OFPlainThread.m +++ src/platform/AmigaOS/OFPlainThread.m @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2008-2021 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#include +#include + +#import "OFPlainThread.h" +#import "OFData.h" +#import "OFTLSKey.h" + +#include +#include +#include + +#ifndef OF_MORPHOS +extern void OFTLSKeyThreadExited(void); +#endif +static OFTLSKey threadKey; + +OF_CONSTRUCTOR() +{ + OFEnsure(OFTLSKeyNew(&threadKey) == 0); +} + +static void +functionWrapper(void) +{ + bool detached = false; + OFPlainThread thread = + (OFPlainThread)((struct Process *)FindTask(NULL))->pr_ExitData; + OFEnsure(OFTLSKeySet(threadKey, thread) == 0); + + thread->function(thread->object); + + ObtainSemaphore(&thread->semaphore); + @try { + thread->done = true; + +#ifndef OF_MORPHOS + OFTLSKeyThreadExited(); +#endif + + if (thread->detached) + detached = true; + else if (thread->joinTask != NULL) + Signal(thread->joinTask, (1ul << thread->joinSigBit)); + } @finally { + ReleaseSemaphore(&thread->semaphore); + } + + if (detached) + free(thread); +} + +int +OFPlainThreadAttributesInit(OFPlainThreadAttributes *attr) +{ + attr->priority = 0; + attr->stackSize = 0; + + return 0; +} + +int +OFPlainThreadNew(OFPlainThread *thread, const char *name, void (*function)(id), + id object, const OFPlainThreadAttributes *attr) +{ + OFMutableData *tags = nil; + + if ((*thread = calloc(1, sizeof(**thread))) == NULL) + return ENOMEM; + + @try { + (*thread)->function = function; + (*thread)->object = object; + InitSemaphore(&(*thread)->semaphore); + + tags = [[OFMutableData alloc] + initWithItemSize: sizeof(struct TagItem) + capacity: 12]; +#define ADD_TAG(tag, data) \ + { \ + struct TagItem t = { \ + .ti_Tag = tag, \ + .ti_Data = data \ + }; \ + [tags addItem: &t]; \ + } + ADD_TAG(NP_Entry, (ULONG)functionWrapper) + ADD_TAG(NP_ExitData, (ULONG)*thread) +#ifdef OF_AMIGAOS4 + ADD_TAG(NP_Child, TRUE) +#endif +#ifdef OF_MORPHOS + ADD_TAG(NP_CodeType, CODETYPE_PPC); +#endif + if (name != NULL) + ADD_TAG(NP_Name, (ULONG)name); + + ADD_TAG(NP_Input, ((struct Process *)FindTask(NULL))->pr_CIS) + ADD_TAG(NP_Output, ((struct Process *)FindTask(NULL))->pr_COS) + ADD_TAG(NP_Error, ((struct Process *)FindTask(NULL))->pr_CES) + ADD_TAG(NP_CloseInput, FALSE) + ADD_TAG(NP_CloseOutput, FALSE) + ADD_TAG(NP_CloseError, FALSE) + + if (attr != NULL && attr->priority != 0) { + if (attr->priority < 1 || attr->priority > 1) + return EINVAL; + + /* + * -1 should be -128 (lowest possible priority) while + * +1 should be +127 (highest possible priority). + */ + ADD_TAG(NP_Priority, (attr->priority > 0 + ? attr->priority * 127 : attr->priority * 128)) + } + + if (attr != NULL && attr->stackSize != 0) + ADD_TAG(NP_StackSize, attr->stackSize) + else + ADD_TAG(NP_StackSize, + ((struct Process *)FindTask(NULL))->pr_StackSize) + + ADD_TAG(TAG_DONE, 0) +#undef ADD_TAG + + (*thread)->task = (struct Task *)CreateNewProc(tags.items); + if ((*thread)->task == NULL) { + free(*thread); + return EAGAIN; + } + } @catch (id e) { + free(*thread); + @throw e; + } @finally { + [tags release]; + } + + return 0; +} + +OFPlainThread +OFCurrentPlainThread(void) +{ + return OFTLSKeyGet(threadKey); +} + +bool +OFPlainThreadIsCurrent(OFPlainThread thread) +{ + return (thread->task == FindTask(NULL)); +} + +int +OFPlainThreadJoin(OFPlainThread thread) +{ + ObtainSemaphore(&thread->semaphore); + + if (thread->done) { + ReleaseSemaphore(&thread->semaphore); + + free(thread); + return 0; + } + + @try { + if (thread->detached || thread->joinTask != NULL) + return EINVAL; + + if ((thread->joinSigBit = AllocSignal(-1)) == -1) + return EAGAIN; + + thread->joinTask = FindTask(NULL); + } @finally { + ReleaseSemaphore(&thread->semaphore); + } + + Wait(1ul << thread->joinSigBit); + FreeSignal(thread->joinSigBit); + + assert(thread->done); + free(thread); + + return 0; +} + +int +OFPlainThreadDetach(OFPlainThread thread) +{ + ObtainSemaphore(&thread->semaphore); + + if (thread->done) + free(thread); + else + thread->detached = true; + + ReleaseSemaphore(&thread->semaphore); + + return 0; +} + +void +OFSetThreadName(const char *name) +{ +} ADDED src/platform/AmigaOS/OFString+PathAdditions.m Index: src/platform/AmigaOS/OFString+PathAdditions.m ================================================================== --- src/platform/AmigaOS/OFString+PathAdditions.m +++ src/platform/AmigaOS/OFString+PathAdditions.m @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2008-2021 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "OFString+PathAdditions.h" +#import "OFArray.h" +#import "OFFileURLHandler.h" + +#import "OFOutOfRangeException.h" + +int _OFString_PathAdditions_reference; + +@implementation OFString (PathAdditions) ++ (OFString *)pathWithComponents: (OFArray *)components +{ + OFMutableString *ret = [OFMutableString string]; + void *pool = objc_autoreleasePoolPush(); + bool firstAfterDevice = true; + + for (OFString *component in components) { + if (component.length == 0) + continue; + + if (!firstAfterDevice) + [ret appendString: @"/"]; + + [ret appendString: component]; + + if (![component hasSuffix: @":"]) + firstAfterDevice = false; + } + + [ret makeImmutable]; + + objc_autoreleasePoolPop(pool); + + return ret; +} + +- (bool)isAbsolutePath +{ + return [self containsString: @":"]; +} + +- (OFArray *)pathComponents +{ + OFMutableArray OF_GENERIC(OFString *) *ret = [OFMutableArray array]; + void *pool = objc_autoreleasePoolPush(); + const char *cString = self.UTF8String; + size_t i, last = 0, cStringLength = self.UTF8StringLength; + + if (cStringLength == 0) { + objc_autoreleasePoolPop(pool); + return ret; + } + + for (i = 0; i < cStringLength; i++) { + if (cString[i] == '/') { + if (i - last != 0) + [ret addObject: [OFString + stringWithUTF8String: cString + last + length: i - last]]; + else + [ret addObject: @"/"]; + + last = i + 1; + } else if (cString[i] == ':') { + [ret addObject: [OFString + stringWithUTF8String: cString + last + length: i - last + 1]]; + + last = i + 1; + } + } + if (i - last != 0) + [ret addObject: [OFString stringWithUTF8String: cString + last + length: i - last]]; + + [ret makeImmutable]; + + objc_autoreleasePoolPop(pool); + + return ret; +} + +- (OFString *)lastPathComponent +{ + /* + * AmigaOS needs the full parsing to determine the last path component. + * This could be optimized by not creating the temporary objects, + * though. + */ + void *pool = objc_autoreleasePoolPush(); + OFString *ret = self.pathComponents.lastObject; + + [ret retain]; + objc_autoreleasePoolPop(pool); + return [ret autorelease]; +} + +- (OFString *)pathExtension +{ + void *pool = objc_autoreleasePoolPush(); + OFString *ret, *fileName; + size_t pos; + + fileName = self.lastPathComponent; + pos = [fileName rangeOfString: @"." + options: OFStringSearchBackwards].location; + if (pos == OFNotFound || pos == 0) { + objc_autoreleasePoolPop(pool); + return @""; + } + + ret = [fileName substringFromIndex: pos + 1]; + + [ret retain]; + objc_autoreleasePoolPop(pool); + return [ret autorelease]; +} + +- (OFString *)stringByDeletingLastPathComponent +{ + /* + * AmigaOS needs the full parsing to delete the last path component. + * This could be optimized, though. + */ + void *pool = objc_autoreleasePoolPush(); + OFArray OF_GENERIC(OFString *) *components = self.pathComponents; + size_t count = components.count; + OFString *ret; + + if (count < 2) { + if ([components.firstObject hasSuffix: @":"]) { + ret = [components.firstObject retain]; + objc_autoreleasePoolPop(pool); + return [ret autorelease]; + } + + objc_autoreleasePoolPop(pool); + return @""; + } + + components = [components objectsInRange: + OFRangeMake(0, components.count - 1)]; + ret = [OFString pathWithComponents: components]; + + [ret retain]; + objc_autoreleasePoolPop(pool); + return [ret autorelease]; +} + +- (OFString *)stringByDeletingPathExtension +{ + void *pool; + OFMutableArray OF_GENERIC(OFString *) *components; + OFString *ret, *fileName; + size_t pos; + + if (self.length == 0) + return [[self copy] autorelease]; + + pool = objc_autoreleasePoolPush(); + components = [[self.pathComponents mutableCopy] autorelease]; + fileName = components.lastObject; + + pos = [fileName rangeOfString: @"." + options: OFStringSearchBackwards].location; + if (pos == OFNotFound || pos == 0) { + objc_autoreleasePoolPop(pool); + return [[self copy] autorelease]; + } + + fileName = [fileName substringToIndex: pos]; + [components replaceObjectAtIndex: components.count - 1 + withObject: fileName]; + + ret = [OFString pathWithComponents: components]; + + [ret retain]; + objc_autoreleasePoolPop(pool); + return [ret autorelease]; +} + +- (OFString *)stringByStandardizingPath +{ + void *pool = objc_autoreleasePoolPush(); + OFArray OF_GENERIC(OFString *) *components; + OFMutableArray OF_GENERIC(OFString *) *array; + OFString *ret; + bool done = false; + + if (self.length == 0) + return @""; + + components = self.pathComponents; + + if (components.count == 1) { + objc_autoreleasePoolPop(pool); + return [[self copy] autorelease]; + } + + array = [[components mutableCopy] autorelease]; + + while (!done) { + size_t length = array.count; + + done = true; + + for (size_t i = 0; i < length; i++) { + OFString *component = [array objectAtIndex: i]; + OFString *parent = + (i > 0 ? [array objectAtIndex: i - 1] : 0); + + if (component.length == 0) { + [array removeObjectAtIndex: i]; + + done = false; + break; + } + + if ([component isEqual: @"/"] && + parent != nil && ![parent isEqual: @"/"]) { + [array removeObjectsInRange: + OFRangeMake(i - 1, 2)]; + + done = false; + break; + } + } + } + + ret = [OFString pathWithComponents: array]; + + if ([self hasSuffix: @"/"]) + ret = [ret stringByAppendingString: @"/"]; + + [ret retain]; + objc_autoreleasePoolPop(pool); + return [ret autorelease]; +} + +- (OFString *)stringByAppendingPathComponent: (OFString *)component +{ + if ([self hasSuffix: @"/"] || [self hasSuffix: @":"]) + return [self stringByAppendingString: component]; + else { + OFMutableString *ret = [[self mutableCopy] autorelease]; + + [ret appendString: @"/"]; + [ret appendString: component]; + + [ret makeImmutable]; + + return ret; + } +} + +- (bool)of_isDirectoryPath +{ + return ([self hasSuffix: @"/"] || [self hasSuffix: @":"] || + [OFFileURLHandler of_directoryExistsAtPath: self]); +} + +- (OFString *)of_pathToURLPathWithURLEncodedHost: (OFString **)URLEncodedHost +{ + OFArray OF_GENERIC(OFString *) *components = self.pathComponents; + OFMutableString *ret = [OFMutableString string]; + + for (OFString *component in components) { + if (component.length == 0) + continue; + + if ([component isEqual: @"/"]) + [ret appendString: @"/.."]; + else { + [ret appendString: @"/"]; + [ret appendString: component]; + } + } + + [ret makeImmutable]; + + return ret; +} + +- (OFString *)of_URLPathToPathWithURLEncodedHost: (OFString *)URLEncodedHost +{ + OFString *path = self; + + if (path.length > 1 && [path hasSuffix: @"/"]) + path = [path substringToIndex: path.length - 1]; + + OFMutableArray OF_GENERIC(OFString *) *components; + size_t count; + + path = [path substringFromIndex: 1]; + components = [[[path + componentsSeparatedByString: @"/"] mutableCopy] autorelease]; + count = components.count; + + for (size_t i = 0; i < count; i++) { + OFString *component = [components objectAtIndex: i]; + + if ([component isEqual: @"."]) { + [components removeObjectAtIndex: i]; + count--; + + i--; + continue; + } + + if ([component isEqual: @".."]) + [components replaceObjectAtIndex: i withObject: @"/"]; + } + + return [OFString pathWithComponents: components]; +} + +- (OFString *)of_pathComponentToURLPathComponent +{ + return self; +} +@end ADDED src/platform/AmigaOS/OFTLSKey.m Index: src/platform/AmigaOS/OFTLSKey.m ================================================================== --- src/platform/AmigaOS/OFTLSKey.m +++ src/platform/AmigaOS/OFTLSKey.m @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2008-2021 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "OFTLSKey.h" + +#include +#include + +/* + * As we use this file in both the runtime and ObjFW, and since AmigaOS always + * has the runtime, use the hashtable from the runtime. + */ +#import "runtime/private.h" + +static OFTLSKey firstKey = NULL, lastKey = NULL; +static struct SignalSemaphore semaphore; +static bool semaphoreInitialized = false; + +static uint32_t +hashFunc(const void *ptr) +{ + return (uint32_t)(uintptr_t)ptr; +} + +static bool +equalFunc(const void *ptr1, const void *ptr2) +{ + return (ptr1 == ptr2); +} + +OF_CONSTRUCTOR() +{ + if (!semaphoreInitialized) { + InitSemaphore(&semaphore); + semaphoreInitialized = true; + } +} + +int +OFTLSKeyNew(OFTLSKey *key) +{ + if (!semaphoreInitialized) { + /* + * We might be called from another constructor, while ours has + * not run yet. This is safe, as the constructor is definitely + * run before a thread is spawned. + */ + InitSemaphore(&semaphore); + semaphoreInitialized = true; + } + + if ((*key = malloc(sizeof(**key))) == NULL) + return ENOMEM; + + (*key)->table = NULL; + + ObtainSemaphore(&semaphore); + @try { + (*key)->next = NULL; + (*key)->previous = lastKey; + + if (lastKey != NULL) + lastKey->next = *key; + + lastKey = *key; + + if (firstKey == NULL) + firstKey = *key; + } @finally { + ReleaseSemaphore(&semaphore); + } + + /* We create the hash table lazily. */ + return 0; +} + +int +OFTLSKeyFree(OFTLSKey key) +{ + ObtainSemaphore(&semaphore); + @try { + if (key->previous != NULL) + key->previous->next = key->next; + if (key->next != NULL) + key->next->previous = key->previous; + + if (firstKey == key) + firstKey = key->next; + if (lastKey == key) + lastKey = key->previous; + + objc_hashtable_free(key->table); + free(key); + } @finally { + ReleaseSemaphore(&semaphore); + } + + return 0; +} + +void * +OFTLSKeyGet(OFTLSKey key) +{ + void *ret; + + ObtainSemaphore(&semaphore); + @try { + if (key->table == NULL) + return NULL; + + ret = objc_hashtable_get(key->table, FindTask(NULL)); + } @finally { + ReleaseSemaphore(&semaphore); + } + + return ret; +} + +int +OFTLSKeySet(OFTLSKey key, void *ptr) +{ + ObtainSemaphore(&semaphore); + @try { + struct Task *task = FindTask(NULL); + + if (key->table == NULL) + key->table = objc_hashtable_new(hashFunc, equalFunc, 2); + + if (ptr == NULL) + objc_hashtable_delete(key->table, task); + else + objc_hashtable_set(key->table, task, ptr); + } @finally { + ReleaseSemaphore(&semaphore); + } + + return 0; +} + +void +OFTLSKeyThreadExited(void) +{ + ObtainSemaphore(&semaphore); + @try { + struct Task *task = FindTask(NULL); + + for (OFTLSKey iter = firstKey; iter != NULL; iter = iter->next) + if (iter->table != NULL) + objc_hashtable_delete(iter->table, task); + } @finally { + ReleaseSemaphore(&semaphore); + } +} ADDED src/platform/GCC4.7/OFAtomic.h Index: src/platform/GCC4.7/OFAtomic.h ================================================================== --- src/platform/GCC4.7/OFAtomic.h +++ src/platform/GCC4.7/OFAtomic.h @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2008-2021 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +static OF_INLINE int +OFAtomicIntAdd(volatile int *_Nonnull p, int i) +{ + return __atomic_add_fetch(p, i, __ATOMIC_RELAXED); +} + +static OF_INLINE int32_t +OFAtomicInt32Add(volatile int32_t *_Nonnull p, int32_t i) +{ + return __atomic_add_fetch(p, i, __ATOMIC_RELAXED); +} + +static OF_INLINE void *_Nullable +OFAtomicPointerAdd(void *volatile _Nullable *_Nonnull p, intptr_t i) +{ + return __atomic_add_fetch(p, i, __ATOMIC_RELAXED); +} + +static OF_INLINE int +OFAtomicIntSubtract(volatile int *_Nonnull p, int i) +{ + return __atomic_sub_fetch(p, i, __ATOMIC_RELAXED); +} + +static OF_INLINE int32_t +OFAtomicInt32Subtract(volatile int32_t *_Nonnull p, int32_t i) +{ + return __atomic_sub_fetch(p, i, __ATOMIC_RELAXED); +} + +static OF_INLINE void *_Nullable +OFAtomicPointerSubtract(void *volatile _Nullable *_Nonnull p, intptr_t i) +{ + return __atomic_sub_fetch(p, i, __ATOMIC_RELAXED); +} + +static OF_INLINE int +OFAtomicIntIncrease(volatile int *_Nonnull p) +{ + return __atomic_add_fetch(p, 1, __ATOMIC_RELAXED); +} + +static OF_INLINE int32_t +OFAtomicInt32Increase(volatile int32_t *_Nonnull p) +{ + return __atomic_add_fetch(p, 1, __ATOMIC_RELAXED); +} + +static OF_INLINE int +OFAtomicIntDecrease(volatile int *_Nonnull p) +{ + return __atomic_sub_fetch(p, 1, __ATOMIC_RELAXED); +} + +static OF_INLINE int32_t +OFAtomicInt32Decrease(volatile int32_t *_Nonnull p) +{ + return __atomic_sub_fetch(p, 1, __ATOMIC_RELAXED); +} + +static OF_INLINE unsigned int +OFAtomicIntOr(volatile unsigned int *_Nonnull p, unsigned int i) +{ + return __atomic_or_fetch(p, i, __ATOMIC_RELAXED); +} + +static OF_INLINE uint32_t +OFAtomicInt32Or(volatile uint32_t *_Nonnull p, uint32_t i) +{ + return __atomic_or_fetch(p, i, __ATOMIC_RELAXED); +} + +static OF_INLINE unsigned int +OFAtomicIntAnd(volatile unsigned int *_Nonnull p, unsigned int i) +{ + return __atomic_and_fetch(p, i, __ATOMIC_RELAXED); +} + +static OF_INLINE uint32_t +OFAtomicInt32And(volatile uint32_t *_Nonnull p, uint32_t i) +{ + return __atomic_and_fetch(p, i, __ATOMIC_RELAXED); +} + +static OF_INLINE unsigned int +OFAtomicIntXor(volatile unsigned int *_Nonnull p, unsigned int i) +{ + return __atomic_xor_fetch(p, i, __ATOMIC_RELAXED); +} + +static OF_INLINE uint32_t +OFAtomicInt32Xor(volatile uint32_t *_Nonnull p, uint32_t i) +{ + return __atomic_xor_fetch(p, i, __ATOMIC_RELAXED); +} + +static OF_INLINE bool +OFAtomicIntCompareAndSwap(volatile int *_Nonnull p, int o, int n) +{ + return __atomic_compare_exchange(p, &o, &n, false, + __ATOMIC_RELAXED, __ATOMIC_RELAXED); +} + +static OF_INLINE bool +OFAtomicInt32CompareAndSwap(volatile int32_t *_Nonnull p, int32_t o, int32_t n) +{ + return __atomic_compare_exchange(p, &o, &n, false, + __ATOMIC_RELAXED, __ATOMIC_RELAXED); +} + +static OF_INLINE bool +OFAtomicPointerCompareAndSwap(void *volatile _Nullable *_Nonnull p, + void *_Nullable o, void *_Nullable n) +{ + return __atomic_compare_exchange(p, &o, &n, false, + __ATOMIC_RELAXED, __ATOMIC_RELAXED); +} + +static OF_INLINE void +OFMemoryBarrier(void) +{ + __atomic_thread_fence(__ATOMIC_SEQ_CST); +} + +static OF_INLINE void +OFAcquireMemoryBarrier(void) +{ + __atomic_thread_fence(__ATOMIC_ACQUIRE); +} + +static OF_INLINE void +OFReleaseMemoryBarrier(void) +{ + __atomic_thread_fence(__ATOMIC_RELEASE); +} ADDED src/platform/GCC4/OFAtomic.h Index: src/platform/GCC4/OFAtomic.h ================================================================== --- src/platform/GCC4/OFAtomic.h +++ src/platform/GCC4/OFAtomic.h @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2008-2021 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +static OF_INLINE int +OFAtomicIntAdd(volatile int *_Nonnull p, int i) +{ + return __sync_add_and_fetch(p, i); +} + +static OF_INLINE int32_t +OFAtomicInt32Add(volatile int32_t *_Nonnull p, int32_t i) +{ + return __sync_add_and_fetch(p, i); +} + +static OF_INLINE void *_Nullable +OFAtomicPointerAdd(void *volatile _Nullable *_Nonnull p, intptr_t i) +{ + return __sync_add_and_fetch(p, (void *)i); +} + +static OF_INLINE int +OFAtomicIntSubtract(volatile int *_Nonnull p, int i) +{ + return __sync_sub_and_fetch(p, i); +} + +static OF_INLINE int32_t +OFAtomicInt32Subtract(volatile int32_t *_Nonnull p, int32_t i) +{ + return __sync_sub_and_fetch(p, i); +} + +static OF_INLINE void *_Nullable +OFAtomicPointerSubtract(void *volatile _Nullable *_Nonnull p, intptr_t i) +{ + return __sync_sub_and_fetch(p, (void *)i); +} + +static OF_INLINE int +OFAtomicIntIncrease(volatile int *_Nonnull p) +{ + return __sync_add_and_fetch(p, 1); +} + +static OF_INLINE int32_t +OFAtomicInt32Increase(volatile int32_t *_Nonnull p) +{ + return __sync_add_and_fetch(p, 1); +} + +static OF_INLINE int +OFAtomicIntDecrease(volatile int *_Nonnull p) +{ + return __sync_sub_and_fetch(p, 1); +} + +static OF_INLINE int32_t +OFAtomicInt32Decrease(volatile int32_t *_Nonnull p) +{ + return __sync_sub_and_fetch(p, 1); +} + +static OF_INLINE unsigned int +OFAtomicIntOr(volatile unsigned int *_Nonnull p, unsigned int i) +{ + return __sync_or_and_fetch(p, i); +} + +static OF_INLINE uint32_t +OFAtomicInt32Or(volatile uint32_t *_Nonnull p, uint32_t i) +{ + return __sync_or_and_fetch(p, i); +} + +static OF_INLINE unsigned int +OFAtomicIntAnd(volatile unsigned int *_Nonnull p, unsigned int i) +{ + return __sync_and_and_fetch(p, i); +} + +static OF_INLINE uint32_t +OFAtomicInt32And(volatile uint32_t *_Nonnull p, uint32_t i) +{ + return __sync_and_and_fetch(p, i); +} + +static OF_INLINE unsigned int +OFAtomicIntXor(volatile unsigned int *_Nonnull p, unsigned int i) +{ + return __sync_xor_and_fetch(p, i); +} + +static OF_INLINE uint32_t +OFAtomicInt32Xor(volatile uint32_t *_Nonnull p, uint32_t i) +{ + return __sync_xor_and_fetch(p, i); +} + +static OF_INLINE bool +OFAtomicIntCompareAndSwap(volatile int *_Nonnull p, int o, int n) +{ + return __sync_bool_compare_and_swap(p, o, n); +} + +static OF_INLINE bool +OFAtomicInt32CompareAndSwap(volatile int32_t *_Nonnull p, int32_t o, int32_t n) +{ + return __sync_bool_compare_and_swap(p, o, n); +} + +static OF_INLINE bool +OFAtomicPointerCompareAndSwap(void *volatile _Nullable *_Nonnull p, + void *_Nullable o, void *_Nullable n) +{ + return __sync_bool_compare_and_swap(p, o, n); +} + +static OF_INLINE void +OFMemoryBarrier(void) +{ + __sync_synchronize(); +} + +static OF_INLINE void +OFAcquireMemoryBarrier(void) +{ + __sync_synchronize(); +} + +static OF_INLINE void +OFReleaseMemoryBarrier(void) +{ + __sync_synchronize(); +} ADDED src/platform/MorphOS/OFTLSKey.m Index: src/platform/MorphOS/OFTLSKey.m ================================================================== --- src/platform/MorphOS/OFTLSKey.m +++ src/platform/MorphOS/OFTLSKey.m @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2008-2021 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "OFTLSKey.h" + +int +OFTLSKeyNew(OFTLSKey *key) +{ + *key = TLSAllocA(NULL); + + if (*key == TLS_INVALID_INDEX) + return EAGAIN; + + return 0; +} + +int +OFTLSKeyFree(OFTLSKey key) +{ + return (TLSFree(key) ? 0 : EINVAL); +} ADDED src/platform/POSIX/OFPlainCondition.m Index: src/platform/POSIX/OFPlainCondition.m ================================================================== --- src/platform/POSIX/OFPlainCondition.m +++ src/platform/POSIX/OFPlainCondition.m @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2008-2021 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "OFPlainCondition.h" + +int +OFPlainConditionNew(OFPlainCondition *condition) +{ + return pthread_cond_init(condition, NULL); +} + +int +OFPlainConditionSignal(OFPlainCondition *condition) +{ + return pthread_cond_signal(condition); +} + +int +OFPlainConditionBroadcast(OFPlainCondition *condition) +{ + return pthread_cond_broadcast(condition); +} + +int +OFPlainConditionWait(OFPlainCondition *condition, OFPlainMutex *mutex) +{ + return pthread_cond_wait(condition, mutex); +} + +int +OFPlainConditionTimedWait(OFPlainCondition *condition, OFPlainMutex *mutex, + OFTimeInterval timeout) +{ + struct timespec ts; + + ts.tv_sec = (time_t)timeout; + ts.tv_nsec = (long)((timeout - ts.tv_sec) * 1000000000); + + return pthread_cond_timedwait(condition, mutex, &ts); +} + +int +OFPlainConditionFree(OFPlainCondition *condition) +{ + return pthread_cond_destroy(condition); +} ADDED src/platform/POSIX/OFPlainMutex.m Index: src/platform/POSIX/OFPlainMutex.m ================================================================== --- src/platform/POSIX/OFPlainMutex.m +++ src/platform/POSIX/OFPlainMutex.m @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2008-2021 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "OFPlainMutex.h" + +int +OFPlainMutexNew(OFPlainMutex *mutex) +{ + return pthread_mutex_init(mutex, NULL); +} + +int +OFPlainMutexLock(OFPlainMutex *mutex) +{ + return pthread_mutex_lock(mutex); +} + +int +OFPlainMutexTryLock(OFPlainMutex *mutex) +{ + return pthread_mutex_trylock(mutex); +} + +int +OFPlainMutexUnlock(OFPlainMutex *mutex) +{ + return pthread_mutex_unlock(mutex); +} + +int +OFPlainMutexFree(OFPlainMutex *mutex) +{ + return pthread_mutex_destroy(mutex); +} + +#ifdef OF_HAVE_RECURSIVE_PTHREAD_MUTEXES +int +OFPlainRecursiveMutexNew(OFPlainRecursiveMutex *rmutex) +{ + int error; + pthread_mutexattr_t attr; + + if ((error = pthread_mutexattr_init(&attr)) != 0) + return error; + + if ((error = pthread_mutexattr_settype(&attr, + PTHREAD_MUTEX_RECURSIVE)) != 0) + return error; + + if ((error = pthread_mutex_init(rmutex, &attr)) != 0) + return error; + + if ((error = pthread_mutexattr_destroy(&attr)) != 0) + return error; + + return 0; +} + +int +OFPlainRecursiveMutexLock(OFPlainRecursiveMutex *rmutex) +{ + return OFPlainMutexLock(rmutex); +} + +int +OFPlainRecursiveMutexTryLock(OFPlainRecursiveMutex *rmutex) +{ + return OFPlainMutexTryLock(rmutex); +} + +int +OFPlainRecursiveMutexUnlock(OFPlainRecursiveMutex *rmutex) +{ + return OFPlainMutexUnlock(rmutex); +} + +int +OFPlainRecursiveMutexFree(OFPlainRecursiveMutex *rmutex) +{ + return OFPlainMutexFree(rmutex); +} +#else +int +OFPlainRecursiveMutexNew(OFPlainRecursiveMutex *rmutex) +{ + int error; + + if ((error = OFPlainMutexNew(&rmutex->mutex)) != 0) + return error; + + if ((error = OFTLSKeyNew(&rmutex->count)) != 0) + return error; + + return 0; +} + +int +OFPlainRecursiveMutexLock(OFPlainRecursiveMutex *rmutex) +{ + uintptr_t count = (uintptr_t)OFTLSKeyGet(rmutex->count); + int error; + + if (count > 0) { + if ((error = OFTLSKeySet(rmutex->count, + (void *)(count + 1))) != 0) + return error; + + return 0; + } + + if ((error = OFPlainMutexLock(&rmutex->mutex)) != 0) + return error; + + if ((error = OFTLSKeySet(rmutex->count, (void *)1)) != 0) { + OFPlainMutexUnlock(&rmutex->mutex); + return error; + } + + return 0; +} + +int +OFPlainRecursiveMutexTryLock(OFPlainRecursiveMutex *rmutex) +{ + uintptr_t count = (uintptr_t)OFTLSKeyGet(rmutex->count); + int error; + + if (count > 0) { + if ((error = OFTLSKeySet(rmutex->count, + (void *)(count + 1))) != 0) + return error; + + return 0; + } + + if ((error = OFPlainMutexTryLock(&rmutex->mutex)) != 0) + return error; + + if ((error = OFTLSKeySet(rmutex->count, (void *)1)) != 0) { + OFPlainMutexUnlock(&rmutex->mutex); + return error; + } + + return 0; +} + +int +OFPlainRecursiveMutexUnlock(OFPlainRecursiveMutex *rmutex) +{ + uintptr_t count = (uintptr_t)OFTLSKeyGet(rmutex->count); + int error; + + if (count > 1) { + if ((error = OFTLSKeySet(rmutex->count, + (void *)(count - 1))) != 0) + return error; + + return 0; + } + + if ((error = OFTLSKeySet(rmutex->count, (void *)0)) != 0) + return error; + + if ((error = OFPlainMutexUnlock(&rmutex->mutex)) != 0) + return error; + + return 0; +} + +int +OFPlainRecursiveMutexFree(OFPlainRecursiveMutex *rmutex) +{ + int error; + + if ((error = OFPlainMutexFree(&rmutex->mutex)) != 0) + return error; + + if ((error = OFTLSKeyFree(rmutex->count)) != 0) + return error; + + return 0; +} +#endif ADDED src/platform/POSIX/OFPlainThread.m Index: src/platform/POSIX/OFPlainThread.m ================================================================== --- src/platform/POSIX/OFPlainThread.m +++ src/platform/POSIX/OFPlainThread.m @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2008-2021 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#include + +#ifdef HAVE_PTHREAD_NP_H +# include +#endif + +#ifdef OF_HAIKU +# include +#endif + +#import "OFPlainThread.h" + +#import "macros.h" + +static int minPrio = 0, maxPrio = 0, normalPrio = 0; + +struct ThreadContext { + void (*function)(id object); + id object; + const char *name; +}; + +/* + * This is done here to make sure this is done as early as possible in the main + * thread. + */ +OF_CONSTRUCTOR() +{ + pthread_attr_t attr; + + if (pthread_attr_init(&attr) == 0) { +#ifdef HAVE_PTHREAD_ATTR_GETSCHEDPOLICY + int policy; +#endif + struct sched_param param; + +#ifdef HAVE_PTHREAD_ATTR_GETSCHEDPOLICY + if (pthread_attr_getschedpolicy(&attr, &policy) == 0) { + minPrio = sched_get_priority_min(policy); + maxPrio = sched_get_priority_max(policy); + + if (minPrio == -1 || maxPrio == -1) + minPrio = maxPrio = 0; + } +#endif + + if (pthread_attr_getschedparam(&attr, ¶m) != 0) + normalPrio = param.sched_priority; + else + minPrio = maxPrio = 0; + + pthread_attr_destroy(&attr); + } +} + +static void * +functionWrapper(void *data) +{ + struct ThreadContext *ctx = data; + + if (ctx->name != NULL) + OFSetThreadName(ctx->name); + + pthread_cleanup_push(free, data); + + ctx->function(ctx->object); + + pthread_cleanup_pop(1); + return NULL; +} + +int +OFPlainThreadAttributesInit(OFPlainThreadAttributes *attr) +{ + int error; + pthread_attr_t POSIXAttr; + + attr->priority = 0; + attr->stackSize = 0; + + if ((error = pthread_attr_init(&POSIXAttr)) != 0) { + if (error == ENOSYS) + return 0; + + return error; + } + + error = pthread_attr_getstacksize(&POSIXAttr, &attr->stackSize); + + pthread_attr_destroy(&POSIXAttr); + + return error; +} + +int +OFPlainThreadNew(OFPlainThread *thread, const char *name, void (*function)(id), + id object, const OFPlainThreadAttributes *attr) +{ + int error = 0; + pthread_attr_t POSIXAttr; + bool POSIXAttrAvailable = true; + + if ((error = pthread_attr_init(&POSIXAttr)) != 0) { + if (error == ENOSYS) + POSIXAttrAvailable = false; + else + return error; + } + + @try { + struct ThreadContext *ctx; + + if (attr != NULL && POSIXAttrAvailable) { +#ifndef OF_HPUX + struct sched_param param; +#endif + + if (attr->priority < -1 || attr->priority > 1) + return EINVAL; + +#ifndef OF_HPUX +# ifdef HAVE_PTHREAD_ATTR_SETINHERITSCHED + if ((error = pthread_attr_setinheritsched(&POSIXAttr, + PTHREAD_EXPLICIT_SCHED)) != 0) + return error; +# endif + + if ((error = pthread_attr_getschedparam(&POSIXAttr, + ¶m)) != 0) + return error; + + if (attr->priority < 0) { + param.sched_priority = minPrio + + (1.0f + attr->priority) * + (normalPrio - minPrio); + } else + param.sched_priority = normalPrio + + attr->priority * (maxPrio - normalPrio); + + if ((error = pthread_attr_setschedparam(&POSIXAttr, + ¶m)) != 0) + return error; +#endif + + if (attr->stackSize > 0) { + if ((error = pthread_attr_setstacksize( + &POSIXAttr, attr->stackSize)) != 0) + return error; + } + } + + if ((ctx = malloc(sizeof(*ctx))) == NULL) + return ENOMEM; + + ctx->function = function; + ctx->object = object; + ctx->name = name; + + error = pthread_create(thread, + (POSIXAttrAvailable ? &POSIXAttr : NULL), functionWrapper, + ctx); + } @finally { + if (POSIXAttrAvailable) + pthread_attr_destroy(&POSIXAttr); + } + + return error; +} + +int +OFPlainThreadJoin(OFPlainThread thread) +{ + void *ret; + + return pthread_join(thread, &ret); +} + +int +OFPlainThreadDetach(OFPlainThread thread) +{ + return pthread_detach(thread); +} + +void +OFSetThreadName(const char *name) +{ +#if defined(OF_HAIKU) + rename_thread(find_thread(NULL), name); +#elif defined(HAVE_PTHREAD_SET_NAME_NP) + pthread_set_name_np(pthread_self(), name); +#elif defined(HAVE_PTHREAD_SETNAME_NP) +# if defined(OF_MACOS) || defined(OF_IOS) + pthread_setname_np(name); +# elif defined(__GLIBC__) + char buffer[16]; + + strncpy(buffer, name, 15); + buffer[15] = 0; + + pthread_setname_np(pthread_self(), buffer); +# endif +#endif +} ADDED src/platform/POSIX/OFString+PathAdditions.m Index: src/platform/POSIX/OFString+PathAdditions.m ================================================================== --- src/platform/POSIX/OFString+PathAdditions.m +++ src/platform/POSIX/OFString+PathAdditions.m @@ -0,0 +1,342 @@ +/* + * Copyright (c) 2008-2021 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "OFString+PathAdditions.h" +#import "OFArray.h" +#import "OFFileURLHandler.h" + +#import "OFOutOfRangeException.h" + +int _OFString_PathAdditions_reference; + +@implementation OFString (PathAdditions) ++ (OFString *)pathWithComponents: (OFArray *)components +{ + OFMutableString *ret = [OFMutableString string]; + void *pool = objc_autoreleasePoolPush(); + bool first = true; + + for (OFString *component in components) { + if (component.length == 0) + continue; + + if (!first && [component isEqual: @"/"]) + continue; + + if (!first && ![ret hasSuffix: @"/"]) + [ret appendString: @"/"]; + + [ret appendString: component]; + + first = false; + } + + [ret makeImmutable]; + + objc_autoreleasePoolPop(pool); + + return ret; +} + +- (bool)isAbsolutePath +{ + return [self hasPrefix: @"/"]; +} + +- (OFArray *)pathComponents +{ + OFMutableArray OF_GENERIC(OFString *) *ret = [OFMutableArray array]; + void *pool = objc_autoreleasePoolPush(); + const char *cString = self.UTF8String; + size_t i, last = 0, cStringLength = self.UTF8StringLength; + + if (cStringLength == 0) { + objc_autoreleasePoolPop(pool); + return ret; + } + + for (i = 0; i < cStringLength; i++) { + if (cString[i] == '/') { + if (i == 0) + [ret addObject: @"/"]; + else if (i - last != 0) + [ret addObject: [OFString + stringWithUTF8String: cString + last + length: i - last]]; + + last = i + 1; + } + } + if (i - last != 0) + [ret addObject: [OFString stringWithUTF8String: cString + last + length: i - last]]; + + [ret makeImmutable]; + + objc_autoreleasePoolPop(pool); + + return ret; +} + +- (OFString *)lastPathComponent +{ + void *pool = objc_autoreleasePoolPush(); + const char *cString = self.UTF8String; + size_t cStringLength = self.UTF8StringLength; + ssize_t i; + OFString *ret; + + if (cStringLength == 0) { + objc_autoreleasePoolPop(pool); + return @""; + } + + if (cString[cStringLength - 1] == '/') + cStringLength--; + + if (cStringLength == 0) { + objc_autoreleasePoolPop(pool); + return @"/"; + } + + if (cStringLength - 1 > SSIZE_MAX) + @throw [OFOutOfRangeException exception]; + + for (i = cStringLength - 1; i >= 0; i--) { + if (cString[i] == '/') { + i++; + break; + } + } + + /* + * Only one component, but the trailing delimiter might have been + * removed, so return a new string anyway. + */ + if (i < 0) + i = 0; + + ret = [[OFString alloc] initWithUTF8String: cString + i + length: cStringLength - i]; + + objc_autoreleasePoolPop(pool); + + return [ret autorelease]; +} + +- (OFString *)pathExtension +{ + void *pool = objc_autoreleasePoolPush(); + OFString *ret, *fileName; + size_t pos; + + fileName = self.lastPathComponent; + pos = [fileName rangeOfString: @"." + options: OFStringSearchBackwards].location; + if (pos == OFNotFound || pos == 0) { + objc_autoreleasePoolPop(pool); + return @""; + } + + ret = [fileName substringFromIndex: pos + 1]; + + [ret retain]; + objc_autoreleasePoolPop(pool); + return [ret autorelease]; +} + +- (OFString *)stringByDeletingLastPathComponent +{ + void *pool = objc_autoreleasePoolPush(); + const char *cString = self.UTF8String; + size_t cStringLength = self.UTF8StringLength; + OFString *ret; + + if (cStringLength == 0) { + objc_autoreleasePoolPop(pool); + return @""; + } + + if (cString[cStringLength - 1] == '/') + cStringLength--; + + if (cStringLength == 0) { + objc_autoreleasePoolPop(pool); + return @"/"; + } + + for (size_t i = cStringLength; i >= 1; i--) { + if (cString[i - 1] == '/') { + if (i == 1) { + objc_autoreleasePoolPop(pool); + return @"/"; + } + + ret = [[OFString alloc] initWithUTF8String: cString + length: i - 1]; + + objc_autoreleasePoolPop(pool); + + return [ret autorelease]; + } + } + + objc_autoreleasePoolPop(pool); + + return @"."; +} + +- (OFString *)stringByDeletingPathExtension +{ + void *pool; + OFMutableArray OF_GENERIC(OFString *) *components; + OFString *ret, *fileName; + size_t pos; + + if (self.length == 0) + return [[self copy] autorelease]; + + pool = objc_autoreleasePoolPush(); + components = [[self.pathComponents mutableCopy] autorelease]; + fileName = components.lastObject; + + pos = [fileName rangeOfString: @"." + options: OFStringSearchBackwards].location; + if (pos == OFNotFound || pos == 0) { + objc_autoreleasePoolPop(pool); + return [[self copy] autorelease]; + } + + fileName = [fileName substringToIndex: pos]; + [components replaceObjectAtIndex: [components count] - 1 + withObject: fileName]; + + ret = [OFString pathWithComponents: components]; + + [ret retain]; + objc_autoreleasePoolPop(pool); + return [ret autorelease]; +} + +- (OFString *)stringByStandardizingPath +{ + void *pool = objc_autoreleasePoolPush(); + OFArray OF_GENERIC(OFString *) *components; + OFMutableArray OF_GENERIC(OFString *) *array; + OFString *ret; + bool done = false, startsWithSlash; + + if (self.length == 0) + return @""; + + components = self.pathComponents; + + if (components.count == 1) { + objc_autoreleasePoolPop(pool); + return [[self copy] autorelease]; + } + + array = [[components mutableCopy] autorelease]; + startsWithSlash = [self hasPrefix: @"/"]; + + if (startsWithSlash) + [array removeObjectAtIndex: 0]; + + while (!done) { + size_t length = array.count; + + done = true; + + for (size_t i = 0; i < length; i++) { + OFString *component = [array objectAtIndex: i]; + OFString *parent = + (i > 0 ? [array objectAtIndex: i - 1] : 0); + + if ([component isEqual: @"."] || + component.length == 0) { + [array removeObjectAtIndex: i]; + + done = false; + break; + } + + if ([component isEqual: @".."] && + parent != nil && ![parent isEqual: @".."]) { + [array removeObjectsInRange: + OFRangeMake(i - 1, 2)]; + + done = false; + break; + } + } + } + + if (startsWithSlash) + [array insertObject: @"" atIndex: 0]; + + if ([self hasSuffix: @"/"]) + [array addObject: @""]; + + ret = [[array componentsJoinedByString: @"/"] retain]; + + objc_autoreleasePoolPop(pool); + + return [ret autorelease]; +} + +- (OFString *)stringByAppendingPathComponent: (OFString *)component +{ + if ([self hasSuffix: @"/"]) + return [self stringByAppendingString: component]; + else { + OFMutableString *ret = [[self mutableCopy] autorelease]; + + [ret appendString: @"/"]; + [ret appendString: component]; + + [ret makeImmutable]; + + return ret; + } +} + +- (bool)of_isDirectoryPath +{ + return ([self hasSuffix: @"/"] || + [OFFileURLHandler of_directoryExistsAtPath: self]); +} + +- (OFString *)of_pathToURLPathWithURLEncodedHost: (OFString **)URLEncodedHost +{ + return self; +} + +- (OFString *)of_URLPathToPathWithURLEncodedHost: (OFString *)URLEncodedHost +{ + OFString *path = self; + + if (path.length > 1 && [path hasSuffix: @"/"]) + path = [path substringToIndex: path.length - 1]; + + return path; +} + +- (OFString *)of_pathComponentToURLPathComponent +{ + return self; +} +@end ADDED src/platform/POSIX/OFSubprocess.m Index: src/platform/POSIX/OFSubprocess.m ================================================================== --- src/platform/POSIX/OFSubprocess.m +++ src/platform/POSIX/OFSubprocess.m @@ -0,0 +1,403 @@ +/* + * Copyright (c) 2008-2021 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#include +#include + +#include + +#ifdef HAVE_SYS_WAIT_H +# include +#endif + +#include "unistd_wrapper.h" +#ifdef HAVE_SPAWN_H +# include +#endif + +#import "OFSubprocess.h" +#import "OFString.h" +#import "OFArray.h" +#import "OFDictionary.h" +#import "OFLocale.h" + +#import "OFInitializationFailedException.h" +#import "OFNotOpenException.h" +#import "OFOutOfRangeException.h" +#import "OFReadFailedException.h" +#import "OFWriteFailedException.h" + +#ifndef HAVE_POSIX_SPAWNP +extern char **environ; +#endif + +@interface OFSubprocess () +- (void)of_getArgv: (char ***)argv + forProgramName: (OFString *)programName + andArguments: (OFArray *)arguments; +- (char **)of_environmentForDictionary: (OFDictionary *)dictionary; +@end + +@implementation OFSubprocess ++ (instancetype)subprocessWithProgram: (OFString *)program +{ + return [[[self alloc] initWithProgram: program] autorelease]; +} + ++ (instancetype)subprocessWithProgram: (OFString *)program + arguments: (OFArray *)arguments +{ + return [[[self alloc] initWithProgram: program + arguments: arguments] autorelease]; +} + ++ (instancetype)subprocessWithProgram: (OFString *)program + programName: (OFString *)programName + arguments: (OFArray *)arguments +{ + return [[[self alloc] initWithProgram: program + programName: programName + arguments: arguments] autorelease]; +} + ++ (instancetype)subprocessWithProgram: (OFString *)program + programName: (OFString *)programName + arguments: (OFArray *)arguments + environment: (OFDictionary *)environment +{ + return [[[self alloc] initWithProgram: program + programName: programName + arguments: arguments + environment: environment] autorelease]; +} + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} + +- (instancetype)initWithProgram: (OFString *)program +{ + return [self initWithProgram: program + programName: program + arguments: nil + environment: nil]; +} + +- (instancetype)initWithProgram: (OFString *)program + arguments: (OFArray *)arguments +{ + return [self initWithProgram: program + programName: program + arguments: arguments + environment: nil]; +} + +- (instancetype)initWithProgram: (OFString *)program + programName: (OFString *)programName + arguments: (OFArray *)arguments +{ + return [self initWithProgram: program + programName: program + arguments: arguments + environment: nil]; +} + +- (instancetype)initWithProgram: (OFString *)program + programName: (OFString *)programName + arguments: (OFArray *)arguments + environment: (OFDictionary *)environment +{ + self = [super init]; + + @try { + void *pool = objc_autoreleasePoolPush(); + const char *path; + char **argv, **env = NULL; + + _pid = -1; + _readPipe[0] = _writePipe[1] = -1; + + if (pipe(_readPipe) != 0 || pipe(_writePipe) != 0) + @throw [OFInitializationFailedException + exceptionWithClass: self.class]; + + path = [program cStringWithEncoding: [OFLocale encoding]]; + [self of_getArgv: &argv + forProgramName: programName + andArguments: arguments]; + + @try { + env = [self of_environmentForDictionary: environment]; +#ifdef HAVE_POSIX_SPAWNP + posix_spawn_file_actions_t actions; + posix_spawnattr_t attr; + + if (posix_spawn_file_actions_init(&actions) != 0) + @throw [OFInitializationFailedException + exceptionWithClass: self.class]; + + if (posix_spawnattr_init(&attr) != 0) { + posix_spawn_file_actions_destroy(&actions); + + @throw [OFInitializationFailedException + exceptionWithClass: self.class]; + } + + @try { + if (posix_spawn_file_actions_addclose(&actions, + _readPipe[0]) != 0 || + posix_spawn_file_actions_addclose(&actions, + _writePipe[1]) != 0 || + posix_spawn_file_actions_adddup2(&actions, + _writePipe[0], 0) != 0 || + posix_spawn_file_actions_adddup2(&actions, + _readPipe[1], 1) != 0) + @throw [OFInitializationFailedException + exceptionWithClass: self.class]; + +# ifdef POSIX_SPAWN_CLOEXEC_DEFAULT + if (posix_spawnattr_setflags(&attr, + POSIX_SPAWN_CLOEXEC_DEFAULT) != 0) + @throw [OFInitializationFailedException + exceptionWithClass: self.class]; +# endif + + if (posix_spawnp(&_pid, path, &actions, &attr, + argv, env) != 0) + @throw [OFInitializationFailedException + exceptionWithClass: self.class]; + } @finally { + posix_spawn_file_actions_destroy(&actions); + posix_spawnattr_destroy(&attr); + } +#else + if ((_pid = vfork()) == 0) { + environ = env; + + close(_readPipe[0]); + close(_writePipe[1]); + dup2(_writePipe[0], 0); + dup2(_readPipe[1], 1); + execvp(path, argv); + + _exit(EXIT_FAILURE); + } + + if (_pid == -1) + @throw [OFInitializationFailedException + exceptionWithClass: self.class]; +#endif + } @finally { + char **iter; + + close(_readPipe[1]); + close(_writePipe[0]); + OFFreeMemory(argv); + + for (iter = env; *iter != NULL; iter++) + OFFreeMemory(*iter); + + OFFreeMemory(env); + } + + objc_autoreleasePoolPop(pool); + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + if (_readPipe[0] != -1) + [self close]; + + [super dealloc]; +} + +- (void)of_getArgv: (char ***)argv + forProgramName: (OFString *)programName + andArguments: (OFArray *)arguments +{ + OFString *const *objects = arguments.objects; + size_t i, count = arguments.count; + OFStringEncoding encoding; + + *argv = OFAllocMemory(count + 2, sizeof(char *)); + + encoding = [OFLocale encoding]; + + (*argv)[0] = (char *)[programName cStringWithEncoding: encoding]; + + for (i = 0; i < count; i++) + (*argv)[i + 1] = + (char *)[objects[i] cStringWithEncoding: encoding]; + + (*argv)[i + 1] = NULL; +} + +- (char **)of_environmentForDictionary: (OFDictionary *)environment +{ + char **envp; + size_t count; + OFStringEncoding encoding; + + if (environment == nil) + return NULL; + + encoding = [OFLocale encoding]; + + count = environment.count; + envp = OFAllocZeroedMemory(count + 1, sizeof(char *)); + + @try { + OFEnumerator *keyEnumerator = [environment keyEnumerator]; + OFEnumerator *objectEnumerator = [environment objectEnumerator]; + + for (size_t i = 0; i < count; i++) { + OFString *key; + OFString *object; + size_t keyLen, objectLen; + + key = [keyEnumerator nextObject]; + object = [objectEnumerator nextObject]; + + keyLen = [key cStringLengthWithEncoding: encoding]; + objectLen = [object + cStringLengthWithEncoding: encoding]; + + envp[i] = OFAllocMemory(keyLen + objectLen + 2, 1); + + memcpy(envp[i], + [key cStringWithEncoding: encoding], keyLen); + envp[i][keyLen] = '='; + memcpy(envp[i] + keyLen + 1, + [object cStringWithEncoding: encoding], objectLen); + envp[i][keyLen + objectLen + 1] = '\0'; + } + } @catch (id e) { + for (size_t i = 0; i < count; i++) + OFFreeMemory(envp[i]); + + OFFreeMemory(envp); + + @throw e; + } + + return envp; +} + +- (bool)lowlevelIsAtEndOfStream +{ + if (_readPipe[0] == -1) + @throw [OFNotOpenException exceptionWithObject: self]; + + return _atEndOfStream; +} + +- (size_t)lowlevelReadIntoBuffer: (void *)buffer + length: (size_t)length +{ + ssize_t ret; + + if (_readPipe[0] == -1) + @throw [OFNotOpenException exceptionWithObject: self]; + + if ((ret = read(_readPipe[0], buffer, length)) < 0) + @throw [OFReadFailedException exceptionWithObject: self + requestedLength: length + errNo: errno]; + + if (ret == 0) + _atEndOfStream = true; + + return ret; +} + +- (size_t)lowlevelWriteBuffer: (const void *)buffer + length: (size_t)length +{ + ssize_t bytesWritten; + + if (_writePipe[1] == -1) + @throw [OFNotOpenException exceptionWithObject: self]; + + if (length > SSIZE_MAX) + @throw [OFOutOfRangeException exception]; + + if ((bytesWritten = write(_writePipe[1], buffer, length)) < 0) + @throw [OFWriteFailedException exceptionWithObject: self + requestedLength: length + bytesWritten: 0 + errNo: errno]; + + return (size_t)bytesWritten; +} + +- (int)fileDescriptorForReading +{ + return _readPipe[0]; +} + +- (int)fileDescriptorForWriting +{ + return _writePipe[1]; +} + +- (void)closeForWriting +{ + if (_writePipe[1] != -1) + close(_writePipe[1]); + + _writePipe[1] = -1; +} + +- (void)close +{ + if (_readPipe[0] == -1) + @throw [OFNotOpenException exceptionWithObject: self]; + + [self closeForWriting]; + close(_readPipe[0]); + + if (_pid != -1) { + kill(_pid, SIGTERM); + waitpid(_pid, &_status, WNOHANG); + } + + _pid = -1; + _readPipe[0] = -1; + + [super close]; +} + +- (int)waitForTermination +{ + if (_readPipe[0] == -1) + @throw [OFNotOpenException exceptionWithObject: self]; + + if (_pid != -1) { + waitpid(_pid, &_status, 0); + _pid = -1; + } + + return WEXITSTATUS(_status); +} +@end ADDED src/platform/POSIX/OFTLSKey.m Index: src/platform/POSIX/OFTLSKey.m ================================================================== --- src/platform/POSIX/OFTLSKey.m +++ src/platform/POSIX/OFTLSKey.m @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2008-2021 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "OFTLSKey.h" + +int +OFTLSKeyNew(OFTLSKey *key) +{ + return pthread_key_create(key, NULL); +} + +int +OFTLSKeyFree(OFTLSKey key) +{ + return pthread_key_delete(key); +} ADDED src/platform/PowerPC/OFAtomic.h Index: src/platform/PowerPC/OFAtomic.h ================================================================== --- src/platform/PowerPC/OFAtomic.h +++ src/platform/PowerPC/OFAtomic.h @@ -0,0 +1,397 @@ +/* + * Copyright (c) 2008-2021 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +static OF_INLINE int +OFAtomicIntAdd(volatile int *_Nonnull p, int i) +{ + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %2\n\t" + "add %0, %0, %1\n\t" + "stwcx. %0, 0, %2\n\t" + "bne- 0b" + : "=&r"(i) + : "r"(i), "r"(p) + : "cc", "memory" + ); + + return i; +} + +static OF_INLINE int32_t +OFAtomicInt32Add(volatile int32_t *_Nonnull p, int32_t i) +{ + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %2\n\t" + "add %0, %0, %1\n\t" + "stwcx. %0, 0, %2\n\t" + "bne- 0b" + : "=&r"(i) + : "r"(i), "r"(p) + : "cc", "memory" + ); + + return i; +} + +static OF_INLINE void *_Nullable +OFAtomicPointerAdd(void *volatile _Nullable *_Nonnull p, intptr_t i) +{ + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %2\n\t" + "add %0, %0, %1\n\t" + "stwcx. %0, 0, %2\n\t" + "bne- 0b" + : "=&r"(i) + : "r"(i), "r"(p) + : "cc", "memory" + ); + + return (void *)i; +} + +static OF_INLINE int +OFAtomicIntSubtract(volatile int *_Nonnull p, int i) +{ + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %2\n\t" + "sub %0, %0, %1\n\t" + "stwcx. %0, 0, %2\n\t" + "bne- 0b" + : "=&r"(i) + : "r"(i), "r"(p) + : "cc", "memory" + ); + + return i; +} + +static OF_INLINE int32_t +OFAtomicInt32Subtract(volatile int32_t *_Nonnull p, int32_t i) +{ + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %2\n\t" + "sub %0, %0, %1\n\t" + "stwcx. %0, 0, %2\n\t" + "bne- 0b" + : "=&r"(i) + : "r"(i), "r"(p) + : "cc", "memory" + ); + + return i; +} + +static OF_INLINE void *_Nullable +OFAtomicPointerSubtract(void *volatile _Nullable *_Nonnull p, intptr_t i) +{ + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %2\n\t" + "sub %0, %0, %1\n\t" + "stwcx. %0, 0, %2\n\t" + "bne- 0b" + : "=&r"(i) + : "r"(i), "r"(p) + : "cc", "memory" + ); + + return (void *)i; +} + +static OF_INLINE int +OFAtomicIntIncrease(volatile int *_Nonnull p) +{ + int i; + + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %1\n\t" + "addi %0, %0, 1\n\t" + "stwcx. %0, 0, %1\n\t" + "bne- 0b" + : "=&r"(i) + : "r"(p) + : "cc", "memory" + ); + + return i; +} + +static OF_INLINE int32_t +OFAtomicInt32Increase(volatile int32_t *_Nonnull p) +{ + int32_t i; + + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %1\n\t" + "addi %0, %0, 1\n\t" + "stwcx. %0, 0, %1\n\t" + "bne- 0b" + : "=&r"(i) + : "r"(p) + : "cc", "memory" + ); + + return i; +} + +static OF_INLINE int +OFAtomicIntDecrease(volatile int *_Nonnull p) +{ + int i; + + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %1\n\t" + "subi %0, %0, 1\n\t" + "stwcx. %0, 0, %1\n\t" + "bne- 0b" + : "=&r"(i) + : "r"(p) + : "cc", "memory" + ); + + return i; +} + +static OF_INLINE int32_t +OFAtomicInt32Decrease(volatile int32_t *_Nonnull p) +{ + int32_t i; + + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %1\n\t" + "subi %0, %0, 1\n\t" + "stwcx. %0, 0, %1\n\t" + "bne- 0b" + : "=&r"(i) + : "r"(p) + : "cc", "memory" + ); + + return i; +} + +static OF_INLINE unsigned int +OFAtomicIntOr(volatile unsigned int *_Nonnull p, unsigned int i) +{ + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %2\n\t" + "or %0, %0, %1\n\t" + "stwcx. %0, 0, %2\n\t" + "bne- 0b" + : "=&r"(i) + : "r"(i), "r"(p) + : "cc", "memory" + ); + + return i; +} + +static OF_INLINE uint32_t +OFAtomicInt32Or(volatile uint32_t *_Nonnull p, uint32_t i) +{ + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %2\n\t" + "or %0, %0, %1\n\t" + "stwcx. %0, 0, %2\n\t" + "bne- 0b" + : "=&r"(i) + : "r"(i), "r"(p) + : "cc", "memory" + ); + + return i; +} + +static OF_INLINE unsigned int +OFAtomicIntAnd(volatile unsigned int *_Nonnull p, unsigned int i) +{ + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %2\n\t" + "and %0, %0, %1\n\t" + "stwcx. %0, 0, %2\n\t" + "bne- 0b" + : "=&r"(i) + : "r"(i), "r"(p) + : "cc", "memory" + ); + + return i; +} + +static OF_INLINE uint32_t +OFAtomicInt32And(volatile uint32_t *_Nonnull p, uint32_t i) +{ + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %2\n\t" + "and %0, %0, %1\n\t" + "stwcx. %0, 0, %2\n\t" + "bne- 0b" + : "=&r"(i) + : "r"(i), "r"(p) + : "cc", "memory" + ); + + return i; +} + +static OF_INLINE unsigned int +OFAtomicIntXor(volatile unsigned int *_Nonnull p, unsigned int i) +{ + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %2\n\t" + "xor %0, %0, %1\n\t" + "stwcx. %0, 0, %2\n\t" + "bne- 0b" + : "=&r"(i) + : "r"(i), "r"(p) + : "cc", "memory" + ); + + return i; +} + +static OF_INLINE uint32_t +OFAtomicInt32Xor(volatile uint32_t *_Nonnull p, uint32_t i) +{ + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %2\n\t" + "xor %0, %0, %1\n\t" + "stwcx. %0, 0, %2\n\t" + "bne- 0b" + : "=&r"(i) + : "r"(i), "r"(p) + : "cc", "memory" + ); + + return i; +} + +static OF_INLINE bool +OFAtomicIntCompareAndSwap(volatile int *_Nonnull p, int o, int n) +{ + int r; + + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %3\n\t" + "cmpw %0, %1\n\t" + "bne 1f\n\t" + "stwcx. %2, 0, %3\n\t" + "bne- 0b\n\t" + "li %0, 1\n\t" + "b 2f\n\t" + "1:\n\t" + "stwcx. %0, 0, %3\n\t" + "li %0, 0\n\t" + "2:" + : "=&r"(r) + : "r"(o), "r"(n), "r"(p) + : "cc", "memory" + ); + + return r; +} + +static OF_INLINE bool +OFAtomicInt32CompareAndSwap(volatile int32_t *_Nonnull p, int32_t o, int32_t n) +{ + int r; + + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %3\n\t" + "cmpw %0, %1\n\t" + "bne 1f\n\t" + "stwcx. %2, 0, %3\n\t" + "bne- 0b\n\t" + "li %0, 1\n\t" + "b 2f\n\t" + "1:\n\t" + "stwcx. %0, 0, %3\n\t" + "li %0, 0\n\t" + "2:" + : "=&r"(r) + : "r"(o), "r"(n), "r"(p) + : "cc", "memory" + ); + + return r; +} + +static OF_INLINE bool +OFAtomicPointerCompareAndSwap(void *volatile _Nullable *_Nonnull p, + void *_Nullable o, void *_Nullable n) +{ + int r; + + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %3\n\t" + "cmpw %0, %1\n\t" + "bne 1f\n\t" + "stwcx. %2, 0, %3\n\t" + "bne- 0b\n\t" + "li %0, 1\n\t" + "b 2f\n\t" + "1:\n\t" + "stwcx. %0, 0, %3\n\t" + "li %0, 0\n\t" + "2:" + : "=&r"(r) + : "r"(o), "r"(n), "r"(p) + : "cc", "memory" + ); + + return r; +} + +static OF_INLINE void +OFMemoryBarrier(void) +{ + __asm__ __volatile__ ( + ".long 0x7C2004AC /* lwsync */" ::: "memory" + ); +} + +static OF_INLINE void +OFAcquireMemoryBarrier(void) +{ + __asm__ __volatile__ ( + ".long 0x7C2004AC /* lwsync */" ::: "memory" + ); +} + +static OF_INLINE void +OFReleaseMemoryBarrier(void) +{ + __asm__ __volatile__ ( + ".long 0x7C2004AC /* lwsync */" ::: "memory" + ); +} ADDED src/platform/Windows/OFPlainCondition.m Index: src/platform/Windows/OFPlainCondition.m ================================================================== --- src/platform/Windows/OFPlainCondition.m +++ src/platform/Windows/OFPlainCondition.m @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2008-2021 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#include + +#import "OFPlainCondition.h" + +#include + +int +OFPlainConditionNew(OFPlainCondition *condition) +{ + condition->count = 0; + + if ((condition->event = CreateEvent(NULL, FALSE, 0, NULL)) == NULL) + return EAGAIN; + + return 0; +} + +int +OFPlainConditionSignal(OFPlainCondition *condition) +{ + if (!SetEvent(condition->event)) { + switch (GetLastError()) { + case ERROR_INVALID_HANDLE: + return EINVAL; + default: + OFEnsure(0); + } + } + + return 0; +} + +int +OFPlainConditionBroadcast(OFPlainCondition *condition) +{ + int count = condition->count; + + for (int i = 0; i < count; i++) { + if (!SetEvent(condition->event)) { + switch (GetLastError()) { + case ERROR_INVALID_HANDLE: + return EINVAL; + default: + OFEnsure(0); + } + } + } + + return 0; +} + +int +OFPlainConditionWait(OFPlainCondition *condition, OFPlainMutex *mutex) +{ + int error; + DWORD status; + + if ((error = OFPlainMutexUnlock(mutex)) != 0) + return error; + + OFAtomicIntIncrease(&condition->count); + status = WaitForSingleObject(condition->event, INFINITE); + OFAtomicIntDecrease(&condition->count); + + switch (status) { + case WAIT_OBJECT_0: + return OFPlainMutexLock(mutex); + case WAIT_FAILED: + switch (GetLastError()) { + case ERROR_INVALID_HANDLE: + return EINVAL; + default: + OFEnsure(0); + } + default: + OFEnsure(0); + } +} + +int +OFPlainConditionTimedWait(OFPlainCondition *condition, OFPlainMutex *mutex, + OFTimeInterval timeout) +{ + int error; + DWORD status; + + if ((error = OFPlainMutexUnlock(mutex)) != 0) + return error; + + OFAtomicIntIncrease(&condition->count); + status = WaitForSingleObject(condition->event, timeout * 1000); + OFAtomicIntDecrease(&condition->count); + + switch (status) { + case WAIT_OBJECT_0: + return OFPlainMutexLock(mutex); + case WAIT_TIMEOUT: + return ETIMEDOUT; + case WAIT_FAILED: + switch (GetLastError()) { + case ERROR_INVALID_HANDLE: + return EINVAL; + default: + OFEnsure(0); + } + default: + OFEnsure(0); + } +} + +int +OFPlainConditionFree(OFPlainCondition *condition) +{ + if (condition->count != 0) + return EBUSY; + + return (CloseHandle(condition->event) ? 0 : EINVAL); +} ADDED src/platform/Windows/OFPlainMutex.m Index: src/platform/Windows/OFPlainMutex.m ================================================================== --- src/platform/Windows/OFPlainMutex.m +++ src/platform/Windows/OFPlainMutex.m @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2008-2021 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#include + +#import "OFPlainMutex.h" + +#include + +int +OFPlainMutexNew(OFPlainMutex *mutex) +{ + InitializeCriticalSection(mutex); + + return 0; +} + +int +OFPlainMutexLock(OFPlainMutex *mutex) +{ + EnterCriticalSection(mutex); + + return 0; +} + +int +OFPlainMutexTryLock(OFPlainMutex *mutex) +{ + if (!TryEnterCriticalSection(mutex)) + return EBUSY; + + return 0; +} + +int +OFPlainMutexUnlock(OFPlainMutex *mutex) +{ + LeaveCriticalSection(mutex); + + return 0; +} + +int +OFPlainMutexFree(OFPlainMutex *mutex) +{ + DeleteCriticalSection(mutex); + + return 0; +} + +int +OFPlainRecursiveMutexNew(OFPlainRecursiveMutex *rmutex) +{ + return OFPlainMutexNew(rmutex); +} + +int +OFPlainRecursiveMutexLock(OFPlainRecursiveMutex *rmutex) +{ + return OFPlainMutexLock(rmutex); +} + +int +OFPlainRecursiveMutexTryLock(OFPlainRecursiveMutex *rmutex) +{ + return OFPlainMutexTryLock(rmutex); +} + +int +OFPlainRecursiveMutexUnlock(OFPlainRecursiveMutex *rmutex) +{ + return OFPlainMutexUnlock(rmutex); +} + +int +OFPlainRecursiveMutexFree(OFPlainRecursiveMutex *rmutex) +{ + return OFPlainMutexFree(rmutex); +} ADDED src/platform/Windows/OFPlainThread.m Index: src/platform/Windows/OFPlainThread.m ================================================================== --- src/platform/Windows/OFPlainThread.m +++ src/platform/Windows/OFPlainThread.m @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2008-2021 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#include + +#import "OFPlainThread.h" + +#import "macros.h" + +#include + +struct ThreadContext { + void (*function)(id); + id object; +}; + +static WINAPI void +functionWrapper(struct ThreadContext *context) +{ + context->function(context->object); + + free(context); +} + +int +OFPlainThreadAttributesInit(OFPlainThreadAttributes *attr) +{ + attr->priority = 0; + attr->stackSize = 0; + + return 0; +} + +int +OFPlainThreadNew(OFPlainThread *thread, const char *name, void (*function)(id), + id object, const OFPlainThreadAttributes *attr) +{ + DWORD priority = THREAD_PRIORITY_NORMAL; + struct ThreadContext *context; + DWORD threadID; + + if (attr != NULL && attr->priority != 0) { + if (attr->priority < -1 || attr->priority > 1) + return EINVAL; + + if (attr->priority < 0) + priority = THREAD_PRIORITY_LOWEST + + (1.0 + attr->priority) * + (THREAD_PRIORITY_NORMAL - THREAD_PRIORITY_LOWEST); + else + priority = THREAD_PRIORITY_NORMAL + + attr->priority * + (THREAD_PRIORITY_HIGHEST - THREAD_PRIORITY_NORMAL); + } + + if ((context = malloc(sizeof(*context))) == NULL) + return ENOMEM; + + context->function = function; + context->object = object; + + *thread = CreateThread(NULL, (attr != NULL ? attr->stackSize : 0), + (LPTHREAD_START_ROUTINE)functionWrapper, context, 0, &threadID); + + if (thread == NULL) { + int error; + + switch (GetLastError()) { + case ERROR_NOT_ENOUGH_MEMORY: + error = ENOMEM; + break; + case ERROR_ACCESS_DENIED: + error = EACCES; + break; + default: + OFEnsure(0); + } + + free(context); + return error; + } + + if (attr != NULL && attr->priority != 0) + OFEnsure(!SetThreadPriority(*thread, priority)); + + return 0; +} + +int +OFPlainThreadJoin(OFPlainThread thread) +{ + switch (WaitForSingleObject(thread, INFINITE)) { + case WAIT_OBJECT_0: + CloseHandle(thread); + return 0; + case WAIT_FAILED: + switch (GetLastError()) { + case ERROR_INVALID_HANDLE: + return EINVAL; + default: + OFEnsure(0); + } + default: + OFEnsure(0); + } +} + +int +OFPlainThreadDetach(OFPlainThread thread) +{ + CloseHandle(thread); + + return 0; +} + +void +OFSetThreadName(const char *name) +{ +} ADDED src/platform/Windows/OFString+PathAdditions.m Index: src/platform/Windows/OFString+PathAdditions.m ================================================================== --- src/platform/Windows/OFString+PathAdditions.m +++ src/platform/Windows/OFString+PathAdditions.m @@ -0,0 +1,382 @@ +/* + * Copyright (c) 2008-2021 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +/* + * This file is also used for MS-DOS! Don't forget to #ifdef Windows-specific + * parts! + */ + +#include "config.h" + +#import "OFString+PathAdditions.h" +#import "OFArray.h" +#import "OFFileURLHandler.h" +#import "OFURL.h" + +#import "OFInvalidFormatException.h" +#import "OFOutOfRangeException.h" + +int _OFString_PathAdditions_reference; + +@implementation OFString (PathAdditions) ++ (OFString *)pathWithComponents: (OFArray *)components +{ + OFMutableString *ret = [OFMutableString string]; + void *pool = objc_autoreleasePoolPush(); + bool first = true; + + for (OFString *component in components) { + if (component.length == 0) + continue; + + if (!first && ![ret hasSuffix: @":"] && + ([component isEqual: @"\\"] || [component isEqual: @"/"])) + continue; + + if (!first && ![ret hasSuffix: @"\\"] && + ![ret hasSuffix: @"/"] && ![ret hasSuffix: @":"]) + [ret appendString: @"\\"]; + + [ret appendString: component]; + + first = false; + } + + [ret makeImmutable]; + + objc_autoreleasePoolPop(pool); + + return ret; +} + +- (bool)isAbsolutePath +{ +#ifdef OF_WINDOWS + if ([self hasPrefix: @"\\\\"]) + return true; +#endif + + return ([self containsString: @":\\"] || [self containsString: @":/"]); +} + +- (OFArray *)pathComponents +{ + OFMutableArray OF_GENERIC(OFString *) *ret = [OFMutableArray array]; + void *pool = objc_autoreleasePoolPush(); + const char *cString = self.UTF8String; + size_t i, last = 0, cStringLength = self.UTF8StringLength; + bool isUNC = false; + + if (cStringLength == 0) { + objc_autoreleasePoolPop(pool); + return ret; + } + +#ifdef OF_WINDOWS + if ([self hasPrefix: @"\\\\"]) { + isUNC = true; + [ret addObject: @"\\\\"]; + + cString += 2; + cStringLength -= 2; + } +#endif + + for (i = 0; i < cStringLength; i++) { + if (cString[i] == '\\' || cString[i] == '/') { + if (i == 0) + [ret addObject: [OFString + stringWithUTF8String: cString + length: 1]]; + else if (i - last != 0) + [ret addObject: [OFString + stringWithUTF8String: cString + last + length: i - last]]; + + last = i + 1; + } else if (!isUNC && cString[i] == ':') { + if (i + 1 < cStringLength && + (cString[i + 1] == '\\' || cString[i + 1] == '/')) + i++; + + [ret addObject: [OFString + stringWithUTF8String: cString + last + length: i - last + 1]]; + + last = i + 1; + } + } + if (i - last != 0) + [ret addObject: [OFString stringWithUTF8String: cString + last + length: i - last]]; + + [ret makeImmutable]; + + objc_autoreleasePoolPop(pool); + + return ret; +} + +- (OFString *)lastPathComponent +{ + /* + * Windows/DOS need the full parsing to determine the last path + * component. This could be optimized by not creating the temporary + * objects, though. + */ + void *pool = objc_autoreleasePoolPush(); + OFString *ret = self.pathComponents.lastObject; + + if (ret == nil) { + objc_autoreleasePoolPop(pool); + return @""; + } + + [ret retain]; + objc_autoreleasePoolPop(pool); + return [ret autorelease]; +} + +- (OFString *)pathExtension +{ + void *pool = objc_autoreleasePoolPush(); + OFString *ret, *fileName; + size_t pos; + + fileName = self.lastPathComponent; + pos = [fileName rangeOfString: @"." + options: OFStringSearchBackwards].location; + if (pos == OFNotFound || pos == 0) { + objc_autoreleasePoolPop(pool); + return @""; + } + + ret = [fileName substringFromIndex: pos + 1]; + + [ret retain]; + objc_autoreleasePoolPop(pool); + return [ret autorelease]; +} + +- (OFString *)stringByDeletingLastPathComponent +{ + /* + * Windows/DOS need the full parsing to delete the last path component. + * This could be optimized, though. + */ + void *pool = objc_autoreleasePoolPush(); + OFArray OF_GENERIC(OFString *) *components = self.pathComponents; + size_t count = components.count; + OFString *ret; + + if (count == 0) { + objc_autoreleasePoolPop(pool); + return @""; + } + + if (count == 1) { + OFString *firstComponent = components.firstObject; + + if ([firstComponent hasSuffix: @":"] || + [firstComponent hasSuffix: @":\\"] || + [firstComponent hasSuffix: @":/"] || + [firstComponent hasPrefix: @"\\"]) { + ret = [firstComponent retain]; + objc_autoreleasePoolPop(pool); + return [ret autorelease]; + } + + objc_autoreleasePoolPop(pool); + return @"."; + } + + components = [components objectsInRange: + OFRangeMake(0, components.count - 1)]; + ret = [OFString pathWithComponents: components]; + + [ret retain]; + objc_autoreleasePoolPop(pool); + return [ret autorelease]; +} + +- (OFString *)stringByDeletingPathExtension +{ + void *pool; + OFMutableArray OF_GENERIC(OFString *) *components; + OFString *ret, *fileName; + size_t pos; + + if (self.length == 0) + return [[self copy] autorelease]; + + pool = objc_autoreleasePoolPush(); + components = [[self.pathComponents mutableCopy] autorelease]; + fileName = components.lastObject; + + pos = [fileName rangeOfString: @"." + options: OFStringSearchBackwards].location; + if (pos == OFNotFound || pos == 0) { + objc_autoreleasePoolPop(pool); + return [[self copy] autorelease]; + } + + fileName = [fileName substringToIndex: pos]; + [components replaceObjectAtIndex: components.count - 1 + withObject: fileName]; + + ret = [OFString pathWithComponents: components]; + + [ret retain]; + objc_autoreleasePoolPop(pool); + return [ret autorelease]; +} + +- (OFString *)stringByStandardizingPath +{ + void *pool = objc_autoreleasePoolPush(); + OFArray OF_GENERIC(OFString *) *components; + OFMutableArray OF_GENERIC(OFString *) *array; + OFString *ret; + bool done = false; + + if (self.length == 0) + return @""; + + components = self.pathComponents; + + if (components.count == 1) { + objc_autoreleasePoolPop(pool); + return [[self copy] autorelease]; + } + + array = [[components mutableCopy] autorelease]; + + while (!done) { + size_t length = array.count; + + done = true; + + for (size_t i = 0; i < length; i++) { + OFString *component = [array objectAtIndex: i]; + OFString *parent = + (i > 0 ? [array objectAtIndex: i - 1] : 0); + + if ([component isEqual: @"."] || + component.length == 0) { + [array removeObjectAtIndex: i]; + + done = false; + break; + } + + if ([component isEqual: @".."] && parent != nil && + ![parent isEqual: @".."] && + ![parent hasSuffix: @":"] && + ![parent hasSuffix: @":\\"] && + ![parent hasSuffix: @"://"] && + (![parent hasPrefix: @"\\"] || i != 1)) { + [array removeObjectsInRange: + OFRangeMake(i - 1, 2)]; + + done = false; + break; + } + } + } + + ret = [[OFString pathWithComponents: array] retain]; + + objc_autoreleasePoolPop(pool); + + return [ret autorelease]; +} + +- (OFString *)stringByAppendingPathComponent: (OFString *)component +{ + if ([self hasSuffix: @"\\"] || [self hasSuffix: @"/"]) + return [self stringByAppendingString: component]; + else { + OFMutableString *ret = [[self mutableCopy] autorelease]; + + [ret appendString: @"\\"]; + [ret appendString: component]; + + [ret makeImmutable]; + + return ret; + } +} + +- (bool)of_isDirectoryPath +{ + return ([self hasSuffix: @"\\"] || [self hasSuffix: @"/"] || + [OFFileURLHandler of_directoryExistsAtPath: self]); +} + +- (OFString *)of_pathToURLPathWithURLEncodedHost: (OFString **)URLEncodedHost +{ + OFString *path = self; + + if ([path hasPrefix: @"\\\\"]) { + OFArray *components = path.pathComponents; + + if (components.count < 2) + @throw [OFInvalidFormatException exception]; + + *URLEncodedHost = [[components objectAtIndex: 1] + stringByURLEncodingWithAllowedCharacters: + [OFCharacterSet URLHostAllowedCharacterSet]]; + path = [OFString pathWithComponents: [components + objectsInRange: OFRangeMake(2, components.count - 2)]]; + } + + path = [path stringByReplacingOccurrencesOfString: @"\\" + withString: @"/"]; + path = [path stringByPrependingString: @"/"]; + + return path; +} + +- (OFString *)of_URLPathToPathWithURLEncodedHost: (OFString *)URLEncodedHost +{ + OFString *path = self; + + if (path.length > 1 && [path hasSuffix: @"/"] && + ![path hasSuffix: @":/"]) + path = [path substringToIndex: path.length - 1]; + + path = [path substringFromIndex: 1]; + path = [path stringByReplacingOccurrencesOfString: @"/" + withString: @"\\"]; + + if (URLEncodedHost != nil) { + OFString *host = [URLEncodedHost stringByURLDecoding]; + + if (path.length == 0) + path = [OFString stringWithFormat: @"\\\\%@", host]; + else + path = [OFString stringWithFormat: @"\\\\%@\\%@", + host, path]; + } + + return path; +} + +- (OFString *)of_pathComponentToURLPathComponent +{ + return [self stringByReplacingOccurrencesOfString: @"\\" + withString: @"/"]; +} +@end ADDED src/platform/Windows/OFSubprocess.m Index: src/platform/Windows/OFSubprocess.m ================================================================== --- src/platform/Windows/OFSubprocess.m +++ src/platform/Windows/OFSubprocess.m @@ -0,0 +1,419 @@ +/* + * Copyright (c) 2008-2021 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#include +#include + +#import "OFSubprocess.h" +#import "OFArray.h" +#import "OFData.h" +#import "OFDictionary.h" +#import "OFLocale.h" +#import "OFString.h" +#import "OFSystemInfo.h" + +#import "OFInitializationFailedException.h" +#import "OFNotOpenException.h" +#import "OFOutOfRangeException.h" +#import "OFReadFailedException.h" +#import "OFWriteFailedException.h" + +#include + +@interface OFSubprocess () +- (OFChar16 *)of_wideEnvironmentForDictionary: (OFDictionary *)dictionary; +- (char *)of_environmentForDictionary: (OFDictionary *)environment; +@end + +@implementation OFSubprocess ++ (instancetype)subprocessWithProgram: (OFString *)program +{ + return [[[self alloc] initWithProgram: program] autorelease]; +} + ++ (instancetype)subprocessWithProgram: (OFString *)program + arguments: (OFArray *)arguments +{ + return [[[self alloc] initWithProgram: program + arguments: arguments] autorelease]; +} + ++ (instancetype)subprocessWithProgram: (OFString *)program + programName: (OFString *)programName + arguments: (OFArray *)arguments +{ + return [[[self alloc] initWithProgram: program + programName: programName + arguments: arguments] autorelease]; +} + ++ (instancetype)subprocessWithProgram: (OFString *)program + programName: (OFString *)programName + arguments: (OFArray *)arguments + environment: (OFDictionary *)environment +{ + return [[[self alloc] initWithProgram: program + programName: programName + arguments: arguments + environment: environment] autorelease]; +} + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} + +- (instancetype)initWithProgram: (OFString *)program +{ + return [self initWithProgram: program + programName: program + arguments: nil + environment: nil]; +} + +- (instancetype)initWithProgram: (OFString *)program + arguments: (OFArray *)arguments +{ + return [self initWithProgram: program + programName: program + arguments: arguments + environment: nil]; +} + +- (instancetype)initWithProgram: (OFString *)program + programName: (OFString *)programName + arguments: (OFArray *)arguments +{ + return [self initWithProgram: program + programName: program + arguments: arguments + environment: nil]; +} + +- (instancetype)initWithProgram: (OFString *)program + programName: (OFString *)programName + arguments: (OFArray *)arguments + environment: (OFDictionary *)environment +{ + self = [super init]; + + @try { + SECURITY_ATTRIBUTES sa; + PROCESS_INFORMATION pi; + void *pool; + OFMutableString *argumentsString; + + _handle = INVALID_HANDLE_VALUE; + _readPipe[0] = _writePipe[1] = NULL; + + sa.nLength = sizeof(sa); + sa.bInheritHandle = TRUE; + sa.lpSecurityDescriptor = NULL; + + if (!CreatePipe(&_readPipe[0], &_readPipe[1], &sa, 0)) + @throw [OFInitializationFailedException + exceptionWithClass: self.class]; + + if (!SetHandleInformation(_readPipe[0], HANDLE_FLAG_INHERIT, 0)) + if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + @throw [OFInitializationFailedException + exceptionWithClass: self.class]; + + if (!CreatePipe(&_writePipe[0], &_writePipe[1], &sa, 0)) + @throw [OFInitializationFailedException + exceptionWithClass: self.class]; + + if (!SetHandleInformation(_writePipe[1], + HANDLE_FLAG_INHERIT, 0)) + if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + @throw [OFInitializationFailedException + exceptionWithClass: self.class]; + + memset(&pi, 0, sizeof(pi)); + + pool = objc_autoreleasePoolPush(); + + argumentsString = + [OFMutableString stringWithString: programName]; + [argumentsString replaceOccurrencesOfString: @"\\\"" + withString: @"\\\\\""]; + [argumentsString replaceOccurrencesOfString: @"\"" + withString: @"\\\""]; + + if ([argumentsString containsString: @" "]) { + [argumentsString prependString: @"\""]; + [argumentsString appendString: @"\""]; + } + + for (OFString *argument in arguments) { + OFMutableString *tmp = + [[argument mutableCopy] autorelease]; + bool containsSpaces = [tmp containsString: @" "]; + + [argumentsString appendString: @" "]; + + if (containsSpaces) + [argumentsString appendString: @"\""]; + + [tmp replaceOccurrencesOfString: @"\\\"" + withString: @"\\\\\""]; + [tmp replaceOccurrencesOfString: @"\"" + withString: @"\\\""]; + + [argumentsString appendString: tmp]; + + if (containsSpaces) + [argumentsString appendString: @"\""]; + } + + if ([OFSystemInfo isWindowsNT]) { + size_t length; + OFChar16 *argumentsCopy; + STARTUPINFOW si; + + memset(&si, 0, sizeof(si)); + si.cb = sizeof(si); + si.hStdInput = _writePipe[0]; + si.hStdOutput = _readPipe[1]; + si.hStdError = GetStdHandle(STD_ERROR_HANDLE); + si.dwFlags |= STARTF_USESTDHANDLES; + + length = argumentsString.UTF16StringLength; + argumentsCopy = OFAllocMemory(length + 1, + sizeof(OFChar16)); + memcpy(argumentsCopy, argumentsString.UTF16String, + (length + 1) * 2); + @try { + if (!CreateProcessW(program.UTF16String, + argumentsCopy, NULL, NULL, TRUE, + CREATE_UNICODE_ENVIRONMENT, + [self of_wideEnvironmentForDictionary: + environment], NULL, &si, &pi)) + @throw [OFInitializationFailedException + exceptionWithClass: self.class]; + } @finally { + OFFreeMemory(argumentsCopy); + } + } else { + OFStringEncoding encoding = [OFLocale encoding]; + STARTUPINFO si; + + memset(&si, 0, sizeof(si)); + si.cb = sizeof(si); + si.hStdInput = _writePipe[0]; + si.hStdOutput = _readPipe[1]; + si.hStdError = GetStdHandle(STD_ERROR_HANDLE); + si.dwFlags |= STARTF_USESTDHANDLES; + + if (!CreateProcessA([program cStringWithEncoding: + encoding], (char *)[argumentsString + cStringWithEncoding: encoding], NULL, NULL, TRUE, 0, + [self of_environmentForDictionary: environment], + NULL, &si, &pi)) + @throw [OFInitializationFailedException + exceptionWithClass: self.class]; + } + + objc_autoreleasePoolPop(pool); + + _handle = pi.hProcess; + CloseHandle(pi.hThread); + + CloseHandle(_readPipe[1]); + CloseHandle(_writePipe[0]); + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + if (_readPipe[0] != NULL) + [self close]; + + [super dealloc]; +} + +- (OFChar16 *)of_wideEnvironmentForDictionary: (OFDictionary *)environment +{ + OFMutableData *env; + OFEnumerator *keyEnumerator, *objectEnumerator; + OFString *key, *object; + const OFChar16 equal = '='; + const OFChar16 zero[2] = { 0, 0 }; + + if (environment == nil) + return NULL; + + env = [OFMutableData dataWithItemSize: sizeof(OFChar16)]; + + keyEnumerator = [environment keyEnumerator]; + objectEnumerator = [environment objectEnumerator]; + while ((key = [keyEnumerator nextObject]) != nil && + (object = [objectEnumerator nextObject]) != nil) { + [env addItems: key.UTF16String count: key.UTF16StringLength]; + [env addItems: &equal count: 1]; + [env addItems: object.UTF16String + count: object.UTF16StringLength]; + [env addItems: &zero count: 1]; + } + [env addItems: zero count: 2]; + + return env.mutableItems; +} + +- (char *)of_environmentForDictionary: (OFDictionary *)environment +{ + OFStringEncoding encoding = [OFLocale encoding]; + OFMutableData *env; + OFEnumerator *keyEnumerator, *objectEnumerator; + OFString *key, *object; + + if (environment == nil) + return NULL; + + env = [OFMutableData data]; + + keyEnumerator = [environment keyEnumerator]; + objectEnumerator = [environment objectEnumerator]; + while ((key = [keyEnumerator nextObject]) != nil && + (object = [objectEnumerator nextObject]) != nil) { + [env addItems: [key cStringWithEncoding: encoding] + count: [key cStringLengthWithEncoding: encoding]]; + [env addItems: "=" count: 1]; + [env addItems: [object cStringWithEncoding: encoding] + count: [object cStringLengthWithEncoding: encoding]]; + [env addItems: "" count: 1]; + } + [env addItems: "\0" count: 2]; + + return env.mutableItems; +} + +- (bool)lowlevelIsAtEndOfStream +{ + if (_readPipe[0] == NULL) + @throw [OFNotOpenException exceptionWithObject: self]; + + return _atEndOfStream; +} + +- (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)length +{ + DWORD ret; + + if (length > UINT32_MAX) + @throw [OFOutOfRangeException exception]; + + if (_readPipe[0] == NULL) + @throw [OFNotOpenException exceptionWithObject: self]; + + if (!ReadFile(_readPipe[0], buffer, (DWORD)length, &ret, NULL)) { + if (GetLastError() == ERROR_BROKEN_PIPE) { + _atEndOfStream = true; + return 0; + } + + @throw [OFReadFailedException exceptionWithObject: self + requestedLength: length + errNo: EIO]; + } + + if (ret == 0) + _atEndOfStream = true; + + return ret; +} + +- (size_t)lowlevelWriteBuffer: (const void *)buffer length: (size_t)length +{ + DWORD bytesWritten; + + if (length > UINT32_MAX) + @throw [OFOutOfRangeException exception]; + + if (_writePipe[1] == NULL) + @throw [OFNotOpenException exceptionWithObject: self]; + + if (!WriteFile(_writePipe[1], buffer, (DWORD)length, &bytesWritten, + NULL)) { + int errNo = EIO; + + if (GetLastError() == ERROR_BROKEN_PIPE) + errNo = EPIPE; + + @throw [OFWriteFailedException exceptionWithObject: self + requestedLength: length + bytesWritten: 0 + errNo: errNo]; + } + + return (size_t)bytesWritten; +} + +- (void)closeForWriting +{ + if (_writePipe[1] != NULL) + CloseHandle(_writePipe[1]); + + _writePipe[1] = NULL; +} + +- (void)close +{ + if (_readPipe[0] == NULL) + @throw [OFNotOpenException exceptionWithObject: self]; + + [self closeForWriting]; + CloseHandle(_readPipe[0]); + + if (_handle != INVALID_HANDLE_VALUE) { + TerminateProcess(_handle, 0); + CloseHandle(_handle); + } + + _handle = INVALID_HANDLE_VALUE; + _readPipe[0] = NULL; + + [super close]; +} + +- (int)waitForTermination +{ + if (_readPipe[0] == NULL) + @throw [OFNotOpenException exceptionWithObject: self]; + + if (_handle != INVALID_HANDLE_VALUE) { + DWORD exitCode; + + WaitForSingleObject(_handle, INFINITE); + + if (GetExitCodeProcess(_handle, &exitCode)) + _status = exitCode; + else + _status = GetLastError(); + + CloseHandle(_handle); + _handle = INVALID_HANDLE_VALUE; + } + + return _status; +} +@end ADDED src/platform/Windows/OFTLSKey.m Index: src/platform/Windows/OFTLSKey.m ================================================================== --- src/platform/Windows/OFTLSKey.m +++ src/platform/Windows/OFTLSKey.m @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2008-2021 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "OFTLSKey.h" + +int +OFTLSKeyNew(OFTLSKey *key) +{ + *key = TlsAlloc(); + + if (*key == TLS_OUT_OF_INDEXES) + return EAGAIN; + + return 0; +} + +int +OFTLSKeyFree(OFTLSKey key) +{ + return (TlsFree(key) ? 0 : EINVAL); +} DELETED src/platform/amiga/OFPlainCondition.m Index: src/platform/amiga/OFPlainCondition.m ================================================================== --- src/platform/amiga/OFPlainCondition.m +++ src/platform/amiga/OFPlainCondition.m @@ -1,251 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#include - -#import "OFPlainCondition.h" - -#include -#include -#ifndef OF_AMIGAOS4 -# include -#endif - -int -OFPlainConditionNew(OFPlainCondition *condition) -{ - condition->waitingTasks = NULL; - - return 0; -} - -int -OFPlainConditionSignal(OFPlainCondition *condition) -{ - Forbid(); - @try { - if (condition->waitingTasks == NULL) - return 0; - - Signal(condition->waitingTasks->task, - (1ul << condition->waitingTasks->sigBit)); - - condition->waitingTasks = condition->waitingTasks->next; - } @finally { - Permit(); - } - - return 0; -} - -int -OFPlainConditionBroadcast(OFPlainCondition *condition) -{ - Forbid(); - @try { - if (condition->waitingTasks == NULL) - return 0; - - while (condition->waitingTasks != NULL) { - Signal(condition->waitingTasks->task, - (1ul << condition->waitingTasks->sigBit)); - - condition->waitingTasks = condition->waitingTasks->next; - } - } @finally { - Permit(); - } - - return 0; -} - -int -OFPlainConditionWait(OFPlainCondition *condition, OFPlainMutex *mutex) -{ - ULONG signalMask = 0; - - return OFPlainConditionWaitOrExecSignal(condition, mutex, &signalMask); -} - -int -OFPlainConditionWaitOrExecSignal(OFPlainCondition *condition, - OFPlainMutex *mutex, ULONG *signalMask) -{ - struct OFPlainConditionWaitingTask waitingTask = { - .task = FindTask(NULL), - .sigBit = AllocSignal(-1) - }; - int error = 0; - ULONG mask; - - if (waitingTask.sigBit == -1) - return EAGAIN; - - Forbid(); - - if ((error = OFPlainMutexUnlock(mutex)) != 0) { - FreeSignal(waitingTask.sigBit); - return error; - } - - waitingTask.next = condition->waitingTasks; - condition->waitingTasks = &waitingTask; - - mask = Wait((1ul << waitingTask.sigBit) | *signalMask); - if (mask & (1ul << waitingTask.sigBit) || (*signalMask &= mask)) - error = OFPlainMutexLock(mutex); - else - /* - * This should not happen - it means something interrupted the - * Wait(), so the best we can do is return EINTR. - */ - error = EINTR; - - FreeSignal(waitingTask.sigBit); - - Permit(); - - return error; -} - -int -OFPlainConditionTimedWait(OFPlainCondition *condition, OFPlainMutex *mutex, - OFTimeInterval timeout) -{ - ULONG signalMask = 0; - - return OFPlainConditionTimedWaitOrExecSignal(condition, mutex, timeout, - &signalMask); -} - -int -OFPlainConditionTimedWaitOrExecSignal(OFPlainCondition *condition, - OFPlainMutex *mutex, OFTimeInterval timeout, ULONG *signalMask) -{ - struct OFPlainConditionWaitingTask waitingTask = { - .task = FindTask(NULL), - .sigBit = AllocSignal(-1) - }; - struct MsgPort port = { - .mp_Node = { - .ln_Type = NT_MSGPORT - }, - .mp_Flags = PA_SIGNAL, - .mp_SigTask = waitingTask.task, - .mp_SigBit = AllocSignal(-1) - }; -#ifdef OF_AMIGAOS4 - struct TimeRequest request = { - .Request = { -#else - struct timerequest request = { - .tr_node = { -#endif - .io_Message = { - .mn_Node = { - .ln_Type = NT_MESSAGE - }, - .mn_ReplyPort = &port, - .mn_Length = sizeof(request) - }, - .io_Command = TR_ADDREQUEST - }, -#ifdef OF_AMIGAOS4 - .Time = { - .Seconds = (ULONG)timeout, - .Microseconds = - (timeout - request.Time.Seconds) * 1000000 -#else - .tr_time = { - .tv_sec = (ULONG)timeout, - .tv_micro = (timeout - request.tr_time.tv_sec) * 1000000 -#endif - } - }; - int error = 0; - ULONG mask; - - NewList(&port.mp_MsgList); - - if (waitingTask.sigBit == -1 || port.mp_SigBit == -1) { - error = EAGAIN; - goto fail; - } - - if (OpenDevice("timer.device", UNIT_MICROHZ, - (struct IORequest *)&request, 0) != 0) { - error = EAGAIN; - goto fail; - } - - Forbid(); - - if ((error = OFPlainMutexUnlock(mutex)) != 0) { - Permit(); - goto fail; - } - - waitingTask.next = condition->waitingTasks; - condition->waitingTasks = &waitingTask; - - SendIO((struct IORequest *)&request); - - mask = Wait((1ul << waitingTask.sigBit) | (1ul << port.mp_SigBit) | - *signalMask); - if (mask & (1ul << waitingTask.sigBit) || (*signalMask &= mask)) - error = OFPlainMutexLock(mutex); - else if (mask & (1ul << port.mp_SigBit)) - error = ETIMEDOUT; - else - /* - * This should not happen - it means something interrupted the - * Wait(), so the best we can do is return EINTR. - */ - error = EINTR; - - condition->waitingTasks = waitingTask.next; - - if (!CheckIO((struct IORequest *)&request)) { - AbortIO((struct IORequest *)&request); - WaitIO((struct IORequest *)&request); - } - CloseDevice((struct IORequest *)&request); - - Permit(); - -fail: - if (waitingTask.sigBit != -1) - FreeSignal(waitingTask.sigBit); - if (port.mp_SigBit != -1) - FreeSignal(port.mp_SigBit); - - return error; -} - -int -OFPlainConditionFree(OFPlainCondition *condition) -{ - Forbid(); - @try { - if (condition->waitingTasks != NULL) - return EBUSY; - } @finally { - Permit(); - } - - return 0; -} DELETED src/platform/amiga/OFPlainMutex.m Index: src/platform/amiga/OFPlainMutex.m ================================================================== --- src/platform/amiga/OFPlainMutex.m +++ src/platform/amiga/OFPlainMutex.m @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#include - -#import "OFPlainMutex.h" - -#include - -int -OFPlainMutexNew(OFPlainMutex *mutex) -{ - InitSemaphore(mutex); - - return 0; -} - -int -OFPlainMutexLock(OFPlainMutex *mutex) -{ - ObtainSemaphore(mutex); - - return 0; -} - -int -OFPlainMutexTryLock(OFPlainMutex *mutex) -{ - if (!AttemptSemaphore(mutex)) - return EBUSY; - - return 0; -} - -int -OFPlainMutexUnlock(OFPlainMutex *mutex) -{ - ReleaseSemaphore(mutex); - - return 0; -} - -int -OFPlainMutexFree(OFPlainMutex *mutex) -{ - return 0; -} - -int -OFPlainRecursiveMutexNew(OFPlainRecursiveMutex *rmutex) -{ - return OFPlainMutexNew(rmutex); -} - -int -OFPlainRecursiveMutexLock(OFPlainRecursiveMutex *rmutex) -{ - return OFPlainMutexLock(rmutex); -} - -int -OFPlainRecursiveMutexTryLock(OFPlainRecursiveMutex *rmutex) -{ - return OFPlainMutexTryLock(rmutex); -} - -int -OFPlainRecursiveMutexUnlock(OFPlainRecursiveMutex *rmutex) -{ - return OFPlainMutexUnlock(rmutex); -} - -int -OFPlainRecursiveMutexFree(OFPlainRecursiveMutex *rmutex) -{ - return OFPlainMutexFree(rmutex); -} DELETED src/platform/amiga/OFPlainThread.m Index: src/platform/amiga/OFPlainThread.m ================================================================== --- src/platform/amiga/OFPlainThread.m +++ src/platform/amiga/OFPlainThread.m @@ -1,214 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#include -#include - -#import "OFPlainThread.h" -#import "OFData.h" -#import "OFTLSKey.h" - -#include -#include -#include - -#ifndef OF_MORPHOS -extern void OFTLSKeyThreadExited(void); -#endif -static OFTLSKey threadKey; - -OF_CONSTRUCTOR() -{ - OFEnsure(OFTLSKeyNew(&threadKey) == 0); -} - -static void -functionWrapper(void) -{ - bool detached = false; - OFPlainThread thread = - (OFPlainThread)((struct Process *)FindTask(NULL))->pr_ExitData; - OFEnsure(OFTLSKeySet(threadKey, thread) == 0); - - thread->function(thread->object); - - ObtainSemaphore(&thread->semaphore); - @try { - thread->done = true; - -#ifndef OF_MORPHOS - OFTLSKeyThreadExited(); -#endif - - if (thread->detached) - detached = true; - else if (thread->joinTask != NULL) - Signal(thread->joinTask, (1ul << thread->joinSigBit)); - } @finally { - ReleaseSemaphore(&thread->semaphore); - } - - if (detached) - free(thread); -} - -int -OFPlainThreadAttributesInit(OFPlainThreadAttributes *attr) -{ - attr->priority = 0; - attr->stackSize = 0; - - return 0; -} - -int -OFPlainThreadNew(OFPlainThread *thread, const char *name, void (*function)(id), - id object, const OFPlainThreadAttributes *attr) -{ - OFMutableData *tags = nil; - - if ((*thread = calloc(1, sizeof(**thread))) == NULL) - return ENOMEM; - - @try { - (*thread)->function = function; - (*thread)->object = object; - InitSemaphore(&(*thread)->semaphore); - - tags = [[OFMutableData alloc] - initWithItemSize: sizeof(struct TagItem) - capacity: 12]; -#define ADD_TAG(tag, data) \ - { \ - struct TagItem t = { \ - .ti_Tag = tag, \ - .ti_Data = data \ - }; \ - [tags addItem: &t]; \ - } - ADD_TAG(NP_Entry, (ULONG)functionWrapper) - ADD_TAG(NP_ExitData, (ULONG)*thread) -#ifdef OF_AMIGAOS4 - ADD_TAG(NP_Child, TRUE) -#endif -#ifdef OF_MORPHOS - ADD_TAG(NP_CodeType, CODETYPE_PPC); -#endif - if (name != NULL) - ADD_TAG(NP_Name, (ULONG)name); - - ADD_TAG(NP_Input, ((struct Process *)FindTask(NULL))->pr_CIS) - ADD_TAG(NP_Output, ((struct Process *)FindTask(NULL))->pr_COS) - ADD_TAG(NP_Error, ((struct Process *)FindTask(NULL))->pr_CES) - ADD_TAG(NP_CloseInput, FALSE) - ADD_TAG(NP_CloseOutput, FALSE) - ADD_TAG(NP_CloseError, FALSE) - - if (attr != NULL && attr->priority != 0) { - if (attr->priority < 1 || attr->priority > 1) - return EINVAL; - - /* - * -1 should be -128 (lowest possible priority) while - * +1 should be +127 (highest possible priority). - */ - ADD_TAG(NP_Priority, (attr->priority > 0 - ? attr->priority * 127 : attr->priority * 128)) - } - - if (attr != NULL && attr->stackSize != 0) - ADD_TAG(NP_StackSize, attr->stackSize) - else - ADD_TAG(NP_StackSize, - ((struct Process *)FindTask(NULL))->pr_StackSize) - - ADD_TAG(TAG_DONE, 0) -#undef ADD_TAG - - (*thread)->task = (struct Task *)CreateNewProc(tags.items); - if ((*thread)->task == NULL) { - free(*thread); - return EAGAIN; - } - } @catch (id e) { - free(*thread); - @throw e; - } @finally { - [tags release]; - } - - return 0; -} - -OFPlainThread -OFCurrentPlainThread(void) -{ - return OFTLSKeyGet(threadKey); -} - -int -OFPlainThreadJoin(OFPlainThread thread) -{ - ObtainSemaphore(&thread->semaphore); - - if (thread->done) { - ReleaseSemaphore(&thread->semaphore); - - free(thread); - return 0; - } - - @try { - if (thread->detached || thread->joinTask != NULL) - return EINVAL; - - if ((thread->joinSigBit = AllocSignal(-1)) == -1) - return EAGAIN; - - thread->joinTask = FindTask(NULL); - } @finally { - ReleaseSemaphore(&thread->semaphore); - } - - Wait(1ul << thread->joinSigBit); - FreeSignal(thread->joinSigBit); - - assert(thread->done); - free(thread); - - return 0; -} - -int -OFPlainThreadDetach(OFPlainThread thread) -{ - ObtainSemaphore(&thread->semaphore); - - if (thread->done) - free(thread); - else - thread->detached = true; - - ReleaseSemaphore(&thread->semaphore); - - return 0; -} - -void -OFSetThreadName(const char *name) -{ -} DELETED src/platform/amiga/OFString+PathAdditions.m Index: src/platform/amiga/OFString+PathAdditions.m ================================================================== --- src/platform/amiga/OFString+PathAdditions.m +++ src/platform/amiga/OFString+PathAdditions.m @@ -1,337 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#import "OFString+PathAdditions.h" -#import "OFArray.h" -#import "OFFileURLHandler.h" - -#import "OFOutOfRangeException.h" - -int _OFString_PathAdditions_reference; - -@implementation OFString (PathAdditions) -+ (OFString *)pathWithComponents: (OFArray *)components -{ - OFMutableString *ret = [OFMutableString string]; - void *pool = objc_autoreleasePoolPush(); - bool firstAfterDevice = true; - - for (OFString *component in components) { - if (component.length == 0) - continue; - - if (!firstAfterDevice) - [ret appendString: @"/"]; - - [ret appendString: component]; - - if (![component hasSuffix: @":"]) - firstAfterDevice = false; - } - - [ret makeImmutable]; - - objc_autoreleasePoolPop(pool); - - return ret; -} - -- (bool)isAbsolutePath -{ - return [self containsString: @":"]; -} - -- (OFArray *)pathComponents -{ - OFMutableArray OF_GENERIC(OFString *) *ret = [OFMutableArray array]; - void *pool = objc_autoreleasePoolPush(); - const char *cString = self.UTF8String; - size_t i, last = 0, cStringLength = self.UTF8StringLength; - - if (cStringLength == 0) { - objc_autoreleasePoolPop(pool); - return ret; - } - - for (i = 0; i < cStringLength; i++) { - if (cString[i] == '/') { - if (i - last != 0) - [ret addObject: [OFString - stringWithUTF8String: cString + last - length: i - last]]; - else - [ret addObject: @"/"]; - - last = i + 1; - } else if (cString[i] == ':') { - [ret addObject: [OFString - stringWithUTF8String: cString + last - length: i - last + 1]]; - - last = i + 1; - } - } - if (i - last != 0) - [ret addObject: [OFString stringWithUTF8String: cString + last - length: i - last]]; - - [ret makeImmutable]; - - objc_autoreleasePoolPop(pool); - - return ret; -} - -- (OFString *)lastPathComponent -{ - /* - * AmigaOS needs the full parsing to determine the last path component. - * This could be optimized by not creating the temporary objects, - * though. - */ - void *pool = objc_autoreleasePoolPush(); - OFString *ret = self.pathComponents.lastObject; - - [ret retain]; - objc_autoreleasePoolPop(pool); - return [ret autorelease]; -} - -- (OFString *)pathExtension -{ - void *pool = objc_autoreleasePoolPush(); - OFString *ret, *fileName; - size_t pos; - - fileName = self.lastPathComponent; - pos = [fileName rangeOfString: @"." - options: OFStringSearchBackwards].location; - if (pos == OFNotFound || pos == 0) { - objc_autoreleasePoolPop(pool); - return @""; - } - - ret = [fileName substringFromIndex: pos + 1]; - - [ret retain]; - objc_autoreleasePoolPop(pool); - return [ret autorelease]; -} - -- (OFString *)stringByDeletingLastPathComponent -{ - /* - * AmigaOS needs the full parsing to delete the last path component. - * This could be optimized, though. - */ - void *pool = objc_autoreleasePoolPush(); - OFArray OF_GENERIC(OFString *) *components = self.pathComponents; - size_t count = components.count; - OFString *ret; - - if (count < 2) { - if ([components.firstObject hasSuffix: @":"]) { - ret = [components.firstObject retain]; - objc_autoreleasePoolPop(pool); - return [ret autorelease]; - } - - objc_autoreleasePoolPop(pool); - return @""; - } - - components = [components objectsInRange: - OFRangeMake(0, components.count - 1)]; - ret = [OFString pathWithComponents: components]; - - [ret retain]; - objc_autoreleasePoolPop(pool); - return [ret autorelease]; -} - -- (OFString *)stringByDeletingPathExtension -{ - void *pool; - OFMutableArray OF_GENERIC(OFString *) *components; - OFString *ret, *fileName; - size_t pos; - - if (self.length == 0) - return [[self copy] autorelease]; - - pool = objc_autoreleasePoolPush(); - components = [[self.pathComponents mutableCopy] autorelease]; - fileName = components.lastObject; - - pos = [fileName rangeOfString: @"." - options: OFStringSearchBackwards].location; - if (pos == OFNotFound || pos == 0) { - objc_autoreleasePoolPop(pool); - return [[self copy] autorelease]; - } - - fileName = [fileName substringToIndex: pos]; - [components replaceObjectAtIndex: components.count - 1 - withObject: fileName]; - - ret = [OFString pathWithComponents: components]; - - [ret retain]; - objc_autoreleasePoolPop(pool); - return [ret autorelease]; -} - -- (OFString *)stringByStandardizingPath -{ - void *pool = objc_autoreleasePoolPush(); - OFArray OF_GENERIC(OFString *) *components; - OFMutableArray OF_GENERIC(OFString *) *array; - OFString *ret; - bool done = false; - - if (self.length == 0) - return @""; - - components = self.pathComponents; - - if (components.count == 1) { - objc_autoreleasePoolPop(pool); - return [[self copy] autorelease]; - } - - array = [[components mutableCopy] autorelease]; - - while (!done) { - size_t length = array.count; - - done = true; - - for (size_t i = 0; i < length; i++) { - OFString *component = [array objectAtIndex: i]; - OFString *parent = - (i > 0 ? [array objectAtIndex: i - 1] : 0); - - if (component.length == 0) { - [array removeObjectAtIndex: i]; - - done = false; - break; - } - - if ([component isEqual: @"/"] && - parent != nil && ![parent isEqual: @"/"]) { - [array removeObjectsInRange: - OFRangeMake(i - 1, 2)]; - - done = false; - break; - } - } - } - - ret = [OFString pathWithComponents: array]; - - if ([self hasSuffix: @"/"]) - ret = [ret stringByAppendingString: @"/"]; - - [ret retain]; - objc_autoreleasePoolPop(pool); - return [ret autorelease]; -} - -- (OFString *)stringByAppendingPathComponent: (OFString *)component -{ - if ([self hasSuffix: @"/"] || [self hasSuffix: @":"]) - return [self stringByAppendingString: component]; - else { - OFMutableString *ret = [[self mutableCopy] autorelease]; - - [ret appendString: @"/"]; - [ret appendString: component]; - - [ret makeImmutable]; - - return ret; - } -} - -- (bool)of_isDirectoryPath -{ - return ([self hasSuffix: @"/"] || [self hasSuffix: @":"] || - [OFFileURLHandler of_directoryExistsAtPath: self]); -} - -- (OFString *)of_pathToURLPathWithURLEncodedHost: (OFString **)URLEncodedHost -{ - OFArray OF_GENERIC(OFString *) *components = self.pathComponents; - OFMutableString *ret = [OFMutableString string]; - - for (OFString *component in components) { - if (component.length == 0) - continue; - - if ([component isEqual: @"/"]) - [ret appendString: @"/.."]; - else { - [ret appendString: @"/"]; - [ret appendString: component]; - } - } - - [ret makeImmutable]; - - return ret; -} - -- (OFString *)of_URLPathToPathWithURLEncodedHost: (OFString *)URLEncodedHost -{ - OFString *path = self; - - if (path.length > 1 && [path hasSuffix: @"/"]) - path = [path substringToIndex: path.length - 1]; - - OFMutableArray OF_GENERIC(OFString *) *components; - size_t count; - - path = [path substringFromIndex: 1]; - components = [[[path - componentsSeparatedByString: @"/"] mutableCopy] autorelease]; - count = components.count; - - for (size_t i = 0; i < count; i++) { - OFString *component = [components objectAtIndex: i]; - - if ([component isEqual: @"."]) { - [components removeObjectAtIndex: i]; - count--; - - i--; - continue; - } - - if ([component isEqual: @".."]) - [components replaceObjectAtIndex: i withObject: @"/"]; - } - - return [OFString pathWithComponents: components]; -} - -- (OFString *)of_pathComponentToURLPathComponent -{ - return self; -} -@end DELETED src/platform/amiga/OFTLSKey.m Index: src/platform/amiga/OFTLSKey.m ================================================================== --- src/platform/amiga/OFTLSKey.m +++ src/platform/amiga/OFTLSKey.m @@ -1,167 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#import "OFTLSKey.h" - -#include -#include - -/* - * As we use this file in both the runtime and ObjFW, and since AmigaOS always - * has the runtime, use the hashtable from the runtime. - */ -#import "runtime/private.h" - -static OFTLSKey firstKey = NULL, lastKey = NULL; -static struct SignalSemaphore semaphore; -static bool semaphoreInitialized = false; - -static uint32_t -hashFunc(const void *ptr) -{ - return (uint32_t)(uintptr_t)ptr; -} - -static bool -equalFunc(const void *ptr1, const void *ptr2) -{ - return (ptr1 == ptr2); -} - -OF_CONSTRUCTOR() -{ - if (!semaphoreInitialized) { - InitSemaphore(&semaphore); - semaphoreInitialized = true; - } -} - -int -OFTLSKeyNew(OFTLSKey *key) -{ - if (!semaphoreInitialized) { - /* - * We might be called from another constructor, while ours has - * not run yet. This is safe, as the constructor is definitely - * run before a thread is spawned. - */ - InitSemaphore(&semaphore); - semaphoreInitialized = true; - } - - if ((*key = malloc(sizeof(**key))) == NULL) - return ENOMEM; - - (*key)->table = NULL; - - ObtainSemaphore(&semaphore); - @try { - (*key)->next = NULL; - (*key)->previous = lastKey; - - if (lastKey != NULL) - lastKey->next = *key; - - lastKey = *key; - - if (firstKey == NULL) - firstKey = *key; - } @finally { - ReleaseSemaphore(&semaphore); - } - - /* We create the hash table lazily. */ - return 0; -} - -int -OFTLSKeyFree(OFTLSKey key) -{ - ObtainSemaphore(&semaphore); - @try { - if (key->previous != NULL) - key->previous->next = key->next; - if (key->next != NULL) - key->next->previous = key->previous; - - if (firstKey == key) - firstKey = key->next; - if (lastKey == key) - lastKey = key->previous; - - objc_hashtable_free(key->table); - free(key); - } @finally { - ReleaseSemaphore(&semaphore); - } - - return 0; -} - -void * -OFTLSKeyGet(OFTLSKey key) -{ - void *ret; - - ObtainSemaphore(&semaphore); - @try { - if (key->table == NULL) - return NULL; - - ret = objc_hashtable_get(key->table, FindTask(NULL)); - } @finally { - ReleaseSemaphore(&semaphore); - } - - return ret; -} - -int -OFTLSKeySet(OFTLSKey key, void *ptr) -{ - ObtainSemaphore(&semaphore); - @try { - struct Task *task = FindTask(NULL); - - if (key->table == NULL) - key->table = objc_hashtable_new(hashFunc, equalFunc, 2); - - if (ptr == NULL) - objc_hashtable_delete(key->table, task); - else - objc_hashtable_set(key->table, task, ptr); - } @finally { - ReleaseSemaphore(&semaphore); - } - - return 0; -} - -void -OFTLSKeyThreadExited(void) -{ - ObtainSemaphore(&semaphore); - @try { - struct Task *task = FindTask(NULL); - - for (OFTLSKey iter = firstKey; iter != NULL; iter = iter->next) - if (iter->table != NULL) - objc_hashtable_delete(iter->table, task); - } @finally { - ReleaseSemaphore(&semaphore); - } -} ADDED src/platform/macOS/OFAtomic.h Index: src/platform/macOS/OFAtomic.h ================================================================== --- src/platform/macOS/OFAtomic.h +++ src/platform/macOS/OFAtomic.h @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2008-2021 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include + +static OF_INLINE int +OFAtomicIntAdd(volatile int *_Nonnull p, int i) +{ + return OSAtomicAdd32(i, p); +} + +static OF_INLINE int32_t +OFAtomicInt32Add(volatile int32_t *_Nonnull p, int32_t i) +{ + return OSAtomicAdd32(i, p); +} + +static OF_INLINE void *_Nullable +OFAtomicPointerAdd(void *volatile _Nullable *_Nonnull p, intptr_t i) +{ +#ifdef __LP64__ + return (void *)OSAtomicAdd64(i, (int64_t *)p); +#else + return (void *)OSAtomicAdd32(i, (int32_t *)p); +#endif +} + +static OF_INLINE int +OFAtomicIntSubtract(volatile int *_Nonnull p, int i) +{ + return OSAtomicAdd32(-i, p); +} + +static OF_INLINE int32_t +OFAtomicInt32Subtract(volatile int32_t *_Nonnull p, int32_t i) +{ + return OSAtomicAdd32(-i, p); +} + +static OF_INLINE void *_Nullable +OFAtomicPointerSubtract(void *volatile _Nullable *_Nonnull p, intptr_t i) +{ +#ifdef __LP64__ + return (void *)OSAtomicAdd64(-i, (int64_t *)p); +#else + return (void *)OSAtomicAdd32(-i, (int32_t *)p); +#endif +} + +static OF_INLINE int +OFAtomicIntIncrease(volatile int *_Nonnull p) +{ + return OSAtomicIncrement32(p); +} + +static OF_INLINE int32_t +OFAtomicInt32Increase(volatile int32_t *_Nonnull p) +{ + return OSAtomicIncrement32(p); +} + +static OF_INLINE int +OFAtomicIntDecrease(volatile int *_Nonnull p) +{ + return OSAtomicDecrement32(p); +} + +static OF_INLINE int32_t +OFAtomicInt32Decrease(volatile int32_t *_Nonnull p) +{ + return OSAtomicDecrement32(p); +} + +static OF_INLINE unsigned int +OFAtomicIntOr(volatile unsigned int *_Nonnull p, unsigned int i) +{ + return OSAtomicOr32(i, p); +} + +static OF_INLINE uint32_t +OFAtomicInt32Or(volatile uint32_t *_Nonnull p, uint32_t i) +{ + return OSAtomicOr32(i, p); +} + +static OF_INLINE unsigned int +OFAtomicIntAnd(volatile unsigned int *_Nonnull p, unsigned int i) +{ + return OSAtomicAnd32(i, p); +} + +static OF_INLINE uint32_t +OFAtomicInt32And(volatile uint32_t *_Nonnull p, uint32_t i) +{ + return OSAtomicAnd32(i, p); +} + +static OF_INLINE unsigned int +OFAtomicIntXor(volatile unsigned int *_Nonnull p, unsigned int i) +{ + return OSAtomicXor32(i, p); +} + +static OF_INLINE uint32_t +OFAtomicInt32Xor(volatile uint32_t *_Nonnull p, uint32_t i) +{ + return OSAtomicXor32(i, p); +} + +static OF_INLINE bool +OFAtomicIntCompareAndSwap(volatile int *_Nonnull p, int o, int n) +{ + return OSAtomicCompareAndSwapInt(o, n, p); +} + +static OF_INLINE bool +OFAtomicInt32CompareAndSwap(volatile int32_t *_Nonnull p, int32_t o, int32_t n) +{ + return OSAtomicCompareAndSwap32(o, n, p); +} + +static OF_INLINE bool +OFAtomicPointerCompareAndSwap(void *volatile _Nullable *_Nonnull p, + void *_Nullable o, void *_Nullable n) +{ + return OSAtomicCompareAndSwapPtr(o, n, p); +} + +static OF_INLINE void +OFMemoryBarrier(void) +{ + OSMemoryBarrier(); +} + +static OF_INLINE void +OFAcquireMemoryBarrier(void) +{ + OSMemoryBarrier(); +} + +static OF_INLINE void +OFReleaseMemoryBarrier(void) +{ + OSMemoryBarrier(); +} DELETED src/platform/morphos/OFTLSKey.m Index: src/platform/morphos/OFTLSKey.m ================================================================== --- src/platform/morphos/OFTLSKey.m +++ src/platform/morphos/OFTLSKey.m @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#import "OFTLSKey.h" - -int -OFTLSKeyNew(OFTLSKeyT *key) -{ - *key = TLSAllocA(NULL); - - if (*key == TLS_INVALID_INDEX) - return EAGAIN; - - return 0; -} - -int -OFTLSKeyFree(OFTLSKeyT key) -{ - return (TLSFree(key) ? 0 : EINVAL); -} DELETED src/platform/posix/OFPlainCondition.m Index: src/platform/posix/OFPlainCondition.m ================================================================== --- src/platform/posix/OFPlainCondition.m +++ src/platform/posix/OFPlainCondition.m @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#import "OFPlainCondition.h" - -int -OFPlainConditionNew(OFPlainCondition *condition) -{ - return pthread_cond_init(condition, NULL); -} - -int -OFPlainConditionSignal(OFPlainCondition *condition) -{ - return pthread_cond_signal(condition); -} - -int -OFPlainConditionBroadcast(OFPlainCondition *condition) -{ - return pthread_cond_broadcast(condition); -} - -int -OFPlainConditionWait(OFPlainCondition *condition, OFPlainMutex *mutex) -{ - return pthread_cond_wait(condition, mutex); -} - -int -OFPlainConditionTimedWait(OFPlainCondition *condition, OFPlainMutex *mutex, - OFTimeInterval timeout) -{ - struct timespec ts; - - ts.tv_sec = (time_t)timeout; - ts.tv_nsec = (long)((timeout - ts.tv_sec) * 1000000000); - - return pthread_cond_timedwait(condition, mutex, &ts); -} - -int -OFPlainConditionFree(OFPlainCondition *condition) -{ - return pthread_cond_destroy(condition); -} DELETED src/platform/posix/OFPlainMutex.m Index: src/platform/posix/OFPlainMutex.m ================================================================== --- src/platform/posix/OFPlainMutex.m +++ src/platform/posix/OFPlainMutex.m @@ -1,197 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#import "OFPlainMutex.h" - -int -OFPlainMutexNew(OFPlainMutex *mutex) -{ - return pthread_mutex_init(mutex, NULL); -} - -int -OFPlainMutexLock(OFPlainMutex *mutex) -{ - return pthread_mutex_lock(mutex); -} - -int -OFPlainMutexTryLock(OFPlainMutex *mutex) -{ - return pthread_mutex_trylock(mutex); -} - -int -OFPlainMutexUnlock(OFPlainMutex *mutex) -{ - return pthread_mutex_unlock(mutex); -} - -int -OFPlainMutexFree(OFPlainMutex *mutex) -{ - return pthread_mutex_destroy(mutex); -} - -#ifdef OF_HAVE_RECURSIVE_PTHREAD_MUTEXES -int -OFPlainRecursiveMutexNew(OFPlainRecursiveMutex *rmutex) -{ - int error; - pthread_mutexattr_t attr; - - if ((error = pthread_mutexattr_init(&attr)) != 0) - return error; - - if ((error = pthread_mutexattr_settype(&attr, - PTHREAD_MUTEX_RECURSIVE)) != 0) - return error; - - if ((error = pthread_mutex_init(rmutex, &attr)) != 0) - return error; - - if ((error = pthread_mutexattr_destroy(&attr)) != 0) - return error; - - return 0; -} - -int -OFPlainRecursiveMutexLock(OFPlainRecursiveMutex *rmutex) -{ - return OFPlainMutexLock(rmutex); -} - -int -OFPlainRecursiveMutexTryLock(OFPlainRecursiveMutex *rmutex) -{ - return OFPlainMutexTryLock(rmutex); -} - -int -OFPlainRecursiveMutexUnlock(OFPlainRecursiveMutex *rmutex) -{ - return OFPlainMutexUnlock(rmutex); -} - -int -OFPlainRecursiveMutexFree(OFPlainRecursiveMutex *rmutex) -{ - return OFPlainMutexFree(rmutex); -} -#else -int -OFPlainRecursiveMutexNew(OFPlainRecursiveMutex *rmutex) -{ - int error; - - if ((error = OFPlainMutexNew(&rmutex->mutex)) != 0) - return error; - - if ((error = OFTLSKeyNew(&rmutex->count)) != 0) - return error; - - return 0; -} - -int -OFPlainRecursiveMutexLock(OFPlainRecursiveMutex *rmutex) -{ - uintptr_t count = (uintptr_t)OFTLSKeyGet(rmutex->count); - int error; - - if (count > 0) { - if ((error = OFTLSKeySet(rmutex->count, - (void *)(count + 1))) != 0) - return error; - - return 0; - } - - if ((error = OFPlainMutexLock(&rmutex->mutex)) != 0) - return error; - - if ((error = OFTLSKeySet(rmutex->count, (void *)1)) != 0) { - OFPlainMutexUnlock(&rmutex->mutex); - return error; - } - - return 0; -} - -int -OFPlainRecursiveMutexTryLock(OFPlainRecursiveMutex *rmutex) -{ - uintptr_t count = (uintptr_t)OFTLSKeyGet(rmutex->count); - int error; - - if (count > 0) { - if ((error = OFTLSKeySet(rmutex->count, - (void *)(count + 1))) != 0) - return error; - - return 0; - } - - if ((error = OFPlainMutexTryLock(&rmutex->mutex)) != 0) - return error; - - if ((error = OFTLSKeySet(rmutex->count, (void *)1)) != 0) { - OFPlainMutexUnlock(&rmutex->mutex); - return error; - } - - return 0; -} - -int -OFPlainRecursiveMutexUnlock(OFPlainRecursiveMutex *rmutex) -{ - uintptr_t count = (uintptr_t)OFTLSKeyGet(rmutex->count); - int error; - - if (count > 1) { - if ((error = OFTLSKeySet(rmutex->count, - (void *)(count - 1))) != 0) - return error; - - return 0; - } - - if ((error = OFTLSKeySet(rmutex->count, (void *)0)) != 0) - return error; - - if ((error = OFPlainMutexUnlock(&rmutex->mutex)) != 0) - return error; - - return 0; -} - -int -OFPlainRecursiveMutexFree(OFPlainRecursiveMutex *rmutex) -{ - int error; - - if ((error = OFPlainMutexFree(&rmutex->mutex)) != 0) - return error; - - if ((error = OFTLSKeyFree(rmutex->count)) != 0) - return error; - - return 0; -} -#endif DELETED src/platform/posix/OFPlainThread.m Index: src/platform/posix/OFPlainThread.m ================================================================== --- src/platform/posix/OFPlainThread.m +++ src/platform/posix/OFPlainThread.m @@ -1,220 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#include - -#ifdef HAVE_PTHREAD_NP_H -# include -#endif - -#ifdef OF_HAIKU -# include -#endif - -#import "OFPlainThread.h" - -#import "macros.h" - -static int minPrio = 0, maxPrio = 0, normalPrio = 0; - -struct ThreadContext { - void (*function)(id object); - id object; - const char *name; -}; - -/* - * This is done here to make sure this is done as early as possible in the main - * thread. - */ -OF_CONSTRUCTOR() -{ - pthread_attr_t attr; - - if (pthread_attr_init(&attr) == 0) { -#ifdef HAVE_PTHREAD_ATTR_GETSCHEDPOLICY - int policy; -#endif - struct sched_param param; - -#ifdef HAVE_PTHREAD_ATTR_GETSCHEDPOLICY - if (pthread_attr_getschedpolicy(&attr, &policy) == 0) { - minPrio = sched_get_priority_min(policy); - maxPrio = sched_get_priority_max(policy); - - if (minPrio == -1 || maxPrio == -1) - minPrio = maxPrio = 0; - } -#endif - - if (pthread_attr_getschedparam(&attr, ¶m) != 0) - normalPrio = param.sched_priority; - else - minPrio = maxPrio = 0; - - pthread_attr_destroy(&attr); - } -} - -static void * -functionWrapper(void *data) -{ - struct ThreadContext *ctx = data; - - if (ctx->name != NULL) - OFSetThreadName(ctx->name); - - pthread_cleanup_push(free, data); - - ctx->function(ctx->object); - - pthread_cleanup_pop(1); - return NULL; -} - -int -OFPlainThreadAttributesInit(OFPlainThreadAttributes *attr) -{ - int error; - pthread_attr_t POSIXAttr; - - attr->priority = 0; - attr->stackSize = 0; - - if ((error = pthread_attr_init(&POSIXAttr)) != 0) { - if (error == ENOSYS) - return 0; - - return error; - } - - error = pthread_attr_getstacksize(&POSIXAttr, &attr->stackSize); - - pthread_attr_destroy(&POSIXAttr); - - return error; -} - -int -OFPlainThreadNew(OFPlainThread *thread, const char *name, void (*function)(id), - id object, const OFPlainThreadAttributes *attr) -{ - int error = 0; - pthread_attr_t POSIXAttr; - bool POSIXAttrAvailable = true; - - if ((error = pthread_attr_init(&POSIXAttr)) != 0) { - if (error == ENOSYS) - POSIXAttrAvailable = false; - else - return error; - } - - @try { - struct ThreadContext *ctx; - - if (attr != NULL && POSIXAttrAvailable) { -#ifndef OF_HPUX - struct sched_param param; -#endif - - if (attr->priority < -1 || attr->priority > 1) - return EINVAL; - -#ifndef OF_HPUX -# ifdef HAVE_PTHREAD_ATTR_SETINHERITSCHED - if ((error = pthread_attr_setinheritsched(&POSIXAttr, - PTHREAD_EXPLICIT_SCHED)) != 0) - return error; -# endif - - if ((error = pthread_attr_getschedparam(&POSIXAttr, - ¶m)) != 0) - return error; - - if (attr->priority < 0) { - param.sched_priority = minPrio + - (1.0f + attr->priority) * - (normalPrio - minPrio); - } else - param.sched_priority = normalPrio + - attr->priority * (maxPrio - normalPrio); - - if ((error = pthread_attr_setschedparam(&POSIXAttr, - ¶m)) != 0) - return error; -#endif - - if (attr->stackSize > 0) { - if ((error = pthread_attr_setstacksize( - &POSIXAttr, attr->stackSize)) != 0) - return error; - } - } - - if ((ctx = malloc(sizeof(*ctx))) == NULL) - return ENOMEM; - - ctx->function = function; - ctx->object = object; - ctx->name = name; - - error = pthread_create(thread, - (POSIXAttrAvailable ? &POSIXAttr : NULL), functionWrapper, - ctx); - } @finally { - if (POSIXAttrAvailable) - pthread_attr_destroy(&POSIXAttr); - } - - return error; -} - -int -OFPlainThreadJoin(OFPlainThread thread) -{ - void *ret; - - return pthread_join(thread, &ret); -} - -int -OFPlainThreadDetach(OFPlainThread thread) -{ - return pthread_detach(thread); -} - -void -OFSetThreadName(const char *name) -{ -#if defined(OF_HAIKU) - rename_thread(find_thread(NULL), name); -#elif defined(HAVE_PTHREAD_SET_NAME_NP) - pthread_set_name_np(pthread_self(), name); -#elif defined(HAVE_PTHREAD_SETNAME_NP) -# if defined(OF_MACOS) || defined(OF_IOS) - pthread_setname_np(name); -# elif defined(__GLIBC__) - char buffer[16]; - - strncpy(buffer, name, 15); - buffer[15] = 0; - - pthread_setname_np(pthread_self(), buffer); -# endif -#endif -} DELETED src/platform/posix/OFString+PathAdditions.m Index: src/platform/posix/OFString+PathAdditions.m ================================================================== --- src/platform/posix/OFString+PathAdditions.m +++ src/platform/posix/OFString+PathAdditions.m @@ -1,342 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#import "OFString+PathAdditions.h" -#import "OFArray.h" -#import "OFFileURLHandler.h" - -#import "OFOutOfRangeException.h" - -int _OFString_PathAdditions_reference; - -@implementation OFString (PathAdditions) -+ (OFString *)pathWithComponents: (OFArray *)components -{ - OFMutableString *ret = [OFMutableString string]; - void *pool = objc_autoreleasePoolPush(); - bool first = true; - - for (OFString *component in components) { - if (component.length == 0) - continue; - - if (!first && [component isEqual: @"/"]) - continue; - - if (!first && ![ret hasSuffix: @"/"]) - [ret appendString: @"/"]; - - [ret appendString: component]; - - first = false; - } - - [ret makeImmutable]; - - objc_autoreleasePoolPop(pool); - - return ret; -} - -- (bool)isAbsolutePath -{ - return [self hasPrefix: @"/"]; -} - -- (OFArray *)pathComponents -{ - OFMutableArray OF_GENERIC(OFString *) *ret = [OFMutableArray array]; - void *pool = objc_autoreleasePoolPush(); - const char *cString = self.UTF8String; - size_t i, last = 0, cStringLength = self.UTF8StringLength; - - if (cStringLength == 0) { - objc_autoreleasePoolPop(pool); - return ret; - } - - for (i = 0; i < cStringLength; i++) { - if (cString[i] == '/') { - if (i == 0) - [ret addObject: @"/"]; - else if (i - last != 0) - [ret addObject: [OFString - stringWithUTF8String: cString + last - length: i - last]]; - - last = i + 1; - } - } - if (i - last != 0) - [ret addObject: [OFString stringWithUTF8String: cString + last - length: i - last]]; - - [ret makeImmutable]; - - objc_autoreleasePoolPop(pool); - - return ret; -} - -- (OFString *)lastPathComponent -{ - void *pool = objc_autoreleasePoolPush(); - const char *cString = self.UTF8String; - size_t cStringLength = self.UTF8StringLength; - ssize_t i; - OFString *ret; - - if (cStringLength == 0) { - objc_autoreleasePoolPop(pool); - return @""; - } - - if (cString[cStringLength - 1] == '/') - cStringLength--; - - if (cStringLength == 0) { - objc_autoreleasePoolPop(pool); - return @"/"; - } - - if (cStringLength - 1 > SSIZE_MAX) - @throw [OFOutOfRangeException exception]; - - for (i = cStringLength - 1; i >= 0; i--) { - if (cString[i] == '/') { - i++; - break; - } - } - - /* - * Only one component, but the trailing delimiter might have been - * removed, so return a new string anyway. - */ - if (i < 0) - i = 0; - - ret = [[OFString alloc] initWithUTF8String: cString + i - length: cStringLength - i]; - - objc_autoreleasePoolPop(pool); - - return [ret autorelease]; -} - -- (OFString *)pathExtension -{ - void *pool = objc_autoreleasePoolPush(); - OFString *ret, *fileName; - size_t pos; - - fileName = self.lastPathComponent; - pos = [fileName rangeOfString: @"." - options: OFStringSearchBackwards].location; - if (pos == OFNotFound || pos == 0) { - objc_autoreleasePoolPop(pool); - return @""; - } - - ret = [fileName substringFromIndex: pos + 1]; - - [ret retain]; - objc_autoreleasePoolPop(pool); - return [ret autorelease]; -} - -- (OFString *)stringByDeletingLastPathComponent -{ - void *pool = objc_autoreleasePoolPush(); - const char *cString = self.UTF8String; - size_t cStringLength = self.UTF8StringLength; - OFString *ret; - - if (cStringLength == 0) { - objc_autoreleasePoolPop(pool); - return @""; - } - - if (cString[cStringLength - 1] == '/') - cStringLength--; - - if (cStringLength == 0) { - objc_autoreleasePoolPop(pool); - return @"/"; - } - - for (size_t i = cStringLength; i >= 1; i--) { - if (cString[i - 1] == '/') { - if (i == 1) { - objc_autoreleasePoolPop(pool); - return @"/"; - } - - ret = [[OFString alloc] initWithUTF8String: cString - length: i - 1]; - - objc_autoreleasePoolPop(pool); - - return [ret autorelease]; - } - } - - objc_autoreleasePoolPop(pool); - - return @"."; -} - -- (OFString *)stringByDeletingPathExtension -{ - void *pool; - OFMutableArray OF_GENERIC(OFString *) *components; - OFString *ret, *fileName; - size_t pos; - - if (self.length == 0) - return [[self copy] autorelease]; - - pool = objc_autoreleasePoolPush(); - components = [[self.pathComponents mutableCopy] autorelease]; - fileName = components.lastObject; - - pos = [fileName rangeOfString: @"." - options: OFStringSearchBackwards].location; - if (pos == OFNotFound || pos == 0) { - objc_autoreleasePoolPop(pool); - return [[self copy] autorelease]; - } - - fileName = [fileName substringToIndex: pos]; - [components replaceObjectAtIndex: [components count] - 1 - withObject: fileName]; - - ret = [OFString pathWithComponents: components]; - - [ret retain]; - objc_autoreleasePoolPop(pool); - return [ret autorelease]; -} - -- (OFString *)stringByStandardizingPath -{ - void *pool = objc_autoreleasePoolPush(); - OFArray OF_GENERIC(OFString *) *components; - OFMutableArray OF_GENERIC(OFString *) *array; - OFString *ret; - bool done = false, startsWithSlash; - - if (self.length == 0) - return @""; - - components = self.pathComponents; - - if (components.count == 1) { - objc_autoreleasePoolPop(pool); - return [[self copy] autorelease]; - } - - array = [[components mutableCopy] autorelease]; - startsWithSlash = [self hasPrefix: @"/"]; - - if (startsWithSlash) - [array removeObjectAtIndex: 0]; - - while (!done) { - size_t length = array.count; - - done = true; - - for (size_t i = 0; i < length; i++) { - OFString *component = [array objectAtIndex: i]; - OFString *parent = - (i > 0 ? [array objectAtIndex: i - 1] : 0); - - if ([component isEqual: @"."] || - component.length == 0) { - [array removeObjectAtIndex: i]; - - done = false; - break; - } - - if ([component isEqual: @".."] && - parent != nil && ![parent isEqual: @".."]) { - [array removeObjectsInRange: - OFRangeMake(i - 1, 2)]; - - done = false; - break; - } - } - } - - if (startsWithSlash) - [array insertObject: @"" atIndex: 0]; - - if ([self hasSuffix: @"/"]) - [array addObject: @""]; - - ret = [[array componentsJoinedByString: @"/"] retain]; - - objc_autoreleasePoolPop(pool); - - return [ret autorelease]; -} - -- (OFString *)stringByAppendingPathComponent: (OFString *)component -{ - if ([self hasSuffix: @"/"]) - return [self stringByAppendingString: component]; - else { - OFMutableString *ret = [[self mutableCopy] autorelease]; - - [ret appendString: @"/"]; - [ret appendString: component]; - - [ret makeImmutable]; - - return ret; - } -} - -- (bool)of_isDirectoryPath -{ - return ([self hasSuffix: @"/"] || - [OFFileURLHandler of_directoryExistsAtPath: self]); -} - -- (OFString *)of_pathToURLPathWithURLEncodedHost: (OFString **)URLEncodedHost -{ - return self; -} - -- (OFString *)of_URLPathToPathWithURLEncodedHost: (OFString *)URLEncodedHost -{ - OFString *path = self; - - if (path.length > 1 && [path hasSuffix: @"/"]) - path = [path substringToIndex: path.length - 1]; - - return path; -} - -- (OFString *)of_pathComponentToURLPathComponent -{ - return self; -} -@end DELETED src/platform/posix/OFSubprocess.m Index: src/platform/posix/OFSubprocess.m ================================================================== --- src/platform/posix/OFSubprocess.m +++ src/platform/posix/OFSubprocess.m @@ -1,403 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#include -#include - -#include - -#ifdef HAVE_SYS_WAIT_H -# include -#endif - -#include "unistd_wrapper.h" -#ifdef HAVE_SPAWN_H -# include -#endif - -#import "OFSubprocess.h" -#import "OFString.h" -#import "OFArray.h" -#import "OFDictionary.h" -#import "OFLocale.h" - -#import "OFInitializationFailedException.h" -#import "OFNotOpenException.h" -#import "OFOutOfRangeException.h" -#import "OFReadFailedException.h" -#import "OFWriteFailedException.h" - -#ifndef HAVE_POSIX_SPAWNP -extern char **environ; -#endif - -@interface OFSubprocess () -- (void)of_getArgv: (char ***)argv - forProgramName: (OFString *)programName - andArguments: (OFArray *)arguments; -- (char **)of_environmentForDictionary: (OFDictionary *)dictionary; -@end - -@implementation OFSubprocess -+ (instancetype)subprocessWithProgram: (OFString *)program -{ - return [[[self alloc] initWithProgram: program] autorelease]; -} - -+ (instancetype)subprocessWithProgram: (OFString *)program - arguments: (OFArray *)arguments -{ - return [[[self alloc] initWithProgram: program - arguments: arguments] autorelease]; -} - -+ (instancetype)subprocessWithProgram: (OFString *)program - programName: (OFString *)programName - arguments: (OFArray *)arguments -{ - return [[[self alloc] initWithProgram: program - programName: programName - arguments: arguments] autorelease]; -} - -+ (instancetype)subprocessWithProgram: (OFString *)program - programName: (OFString *)programName - arguments: (OFArray *)arguments - environment: (OFDictionary *)environment -{ - return [[[self alloc] initWithProgram: program - programName: programName - arguments: arguments - environment: environment] autorelease]; -} - -- (instancetype)init -{ - OF_INVALID_INIT_METHOD -} - -- (instancetype)initWithProgram: (OFString *)program -{ - return [self initWithProgram: program - programName: program - arguments: nil - environment: nil]; -} - -- (instancetype)initWithProgram: (OFString *)program - arguments: (OFArray *)arguments -{ - return [self initWithProgram: program - programName: program - arguments: arguments - environment: nil]; -} - -- (instancetype)initWithProgram: (OFString *)program - programName: (OFString *)programName - arguments: (OFArray *)arguments -{ - return [self initWithProgram: program - programName: program - arguments: arguments - environment: nil]; -} - -- (instancetype)initWithProgram: (OFString *)program - programName: (OFString *)programName - arguments: (OFArray *)arguments - environment: (OFDictionary *)environment -{ - self = [super init]; - - @try { - void *pool = objc_autoreleasePoolPush(); - const char *path; - char **argv, **env = NULL; - - _pid = -1; - _readPipe[0] = _writePipe[1] = -1; - - if (pipe(_readPipe) != 0 || pipe(_writePipe) != 0) - @throw [OFInitializationFailedException - exceptionWithClass: self.class]; - - path = [program cStringWithEncoding: [OFLocale encoding]]; - [self of_getArgv: &argv - forProgramName: programName - andArguments: arguments]; - - @try { - env = [self of_environmentForDictionary: environment]; -#ifdef HAVE_POSIX_SPAWNP - posix_spawn_file_actions_t actions; - posix_spawnattr_t attr; - - if (posix_spawn_file_actions_init(&actions) != 0) - @throw [OFInitializationFailedException - exceptionWithClass: self.class]; - - if (posix_spawnattr_init(&attr) != 0) { - posix_spawn_file_actions_destroy(&actions); - - @throw [OFInitializationFailedException - exceptionWithClass: self.class]; - } - - @try { - if (posix_spawn_file_actions_addclose(&actions, - _readPipe[0]) != 0 || - posix_spawn_file_actions_addclose(&actions, - _writePipe[1]) != 0 || - posix_spawn_file_actions_adddup2(&actions, - _writePipe[0], 0) != 0 || - posix_spawn_file_actions_adddup2(&actions, - _readPipe[1], 1) != 0) - @throw [OFInitializationFailedException - exceptionWithClass: self.class]; - -# ifdef POSIX_SPAWN_CLOEXEC_DEFAULT - if (posix_spawnattr_setflags(&attr, - POSIX_SPAWN_CLOEXEC_DEFAULT) != 0) - @throw [OFInitializationFailedException - exceptionWithClass: self.class]; -# endif - - if (posix_spawnp(&_pid, path, &actions, &attr, - argv, env) != 0) - @throw [OFInitializationFailedException - exceptionWithClass: self.class]; - } @finally { - posix_spawn_file_actions_destroy(&actions); - posix_spawnattr_destroy(&attr); - } -#else - if ((_pid = vfork()) == 0) { - environ = env; - - close(_readPipe[0]); - close(_writePipe[1]); - dup2(_writePipe[0], 0); - dup2(_readPipe[1], 1); - execvp(path, argv); - - _exit(EXIT_FAILURE); - } - - if (_pid == -1) - @throw [OFInitializationFailedException - exceptionWithClass: self.class]; -#endif - } @finally { - char **iter; - - close(_readPipe[1]); - close(_writePipe[0]); - OFFreeMemory(argv); - - for (iter = env; *iter != NULL; iter++) - OFFreeMemory(*iter); - - OFFreeMemory(env); - } - - objc_autoreleasePoolPop(pool); - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)dealloc -{ - if (_readPipe[0] != -1) - [self close]; - - [super dealloc]; -} - -- (void)of_getArgv: (char ***)argv - forProgramName: (OFString *)programName - andArguments: (OFArray *)arguments -{ - OFString *const *objects = arguments.objects; - size_t i, count = arguments.count; - OFStringEncoding encoding; - - *argv = OFAllocMemory(count + 2, sizeof(char *)); - - encoding = [OFLocale encoding]; - - (*argv)[0] = (char *)[programName cStringWithEncoding: encoding]; - - for (i = 0; i < count; i++) - (*argv)[i + 1] = - (char *)[objects[i] cStringWithEncoding: encoding]; - - (*argv)[i + 1] = NULL; -} - -- (char **)of_environmentForDictionary: (OFDictionary *)environment -{ - char **envp; - size_t count; - OFStringEncoding encoding; - - if (environment == nil) - return NULL; - - encoding = [OFLocale encoding]; - - count = environment.count; - envp = OFAllocZeroedMemory(count + 1, sizeof(char *)); - - @try { - OFEnumerator *keyEnumerator = [environment keyEnumerator]; - OFEnumerator *objectEnumerator = [environment objectEnumerator]; - - for (size_t i = 0; i < count; i++) { - OFString *key; - OFString *object; - size_t keyLen, objectLen; - - key = [keyEnumerator nextObject]; - object = [objectEnumerator nextObject]; - - keyLen = [key cStringLengthWithEncoding: encoding]; - objectLen = [object - cStringLengthWithEncoding: encoding]; - - envp[i] = OFAllocMemory(keyLen + objectLen + 2, 1); - - memcpy(envp[i], - [key cStringWithEncoding: encoding], keyLen); - envp[i][keyLen] = '='; - memcpy(envp[i] + keyLen + 1, - [object cStringWithEncoding: encoding], objectLen); - envp[i][keyLen + objectLen + 1] = '\0'; - } - } @catch (id e) { - for (size_t i = 0; i < count; i++) - OFFreeMemory(envp[i]); - - OFFreeMemory(envp); - - @throw e; - } - - return envp; -} - -- (bool)lowlevelIsAtEndOfStream -{ - if (_readPipe[0] == -1) - @throw [OFNotOpenException exceptionWithObject: self]; - - return _atEndOfStream; -} - -- (size_t)lowlevelReadIntoBuffer: (void *)buffer - length: (size_t)length -{ - ssize_t ret; - - if (_readPipe[0] == -1) - @throw [OFNotOpenException exceptionWithObject: self]; - - if ((ret = read(_readPipe[0], buffer, length)) < 0) - @throw [OFReadFailedException exceptionWithObject: self - requestedLength: length - errNo: errno]; - - if (ret == 0) - _atEndOfStream = true; - - return ret; -} - -- (size_t)lowlevelWriteBuffer: (const void *)buffer - length: (size_t)length -{ - ssize_t bytesWritten; - - if (_writePipe[1] == -1) - @throw [OFNotOpenException exceptionWithObject: self]; - - if (length > SSIZE_MAX) - @throw [OFOutOfRangeException exception]; - - if ((bytesWritten = write(_writePipe[1], buffer, length)) < 0) - @throw [OFWriteFailedException exceptionWithObject: self - requestedLength: length - bytesWritten: 0 - errNo: errno]; - - return (size_t)bytesWritten; -} - -- (int)fileDescriptorForReading -{ - return _readPipe[0]; -} - -- (int)fileDescriptorForWriting -{ - return _writePipe[1]; -} - -- (void)closeForWriting -{ - if (_writePipe[1] != -1) - close(_writePipe[1]); - - _writePipe[1] = -1; -} - -- (void)close -{ - if (_readPipe[0] == -1) - @throw [OFNotOpenException exceptionWithObject: self]; - - [self closeForWriting]; - close(_readPipe[0]); - - if (_pid != -1) { - kill(_pid, SIGTERM); - waitpid(_pid, &_status, WNOHANG); - } - - _pid = -1; - _readPipe[0] = -1; - - [super close]; -} - -- (int)waitForTermination -{ - if (_readPipe[0] == -1) - @throw [OFNotOpenException exceptionWithObject: self]; - - if (_pid != -1) { - waitpid(_pid, &_status, 0); - _pid = -1; - } - - return WEXITSTATUS(_status); -} -@end DELETED src/platform/posix/OFTLSKey.m Index: src/platform/posix/OFTLSKey.m ================================================================== --- src/platform/posix/OFTLSKey.m +++ src/platform/posix/OFTLSKey.m @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#import "OFTLSKey.h" - -int -OFTLSKeyNew(OFTLSKey *key) -{ - return pthread_key_create(key, NULL); -} - -int -OFTLSKeyFree(OFTLSKey key) -{ - return pthread_key_delete(key); -} DELETED src/platform/windows/OFPlainCondition.m Index: src/platform/windows/OFPlainCondition.m ================================================================== --- src/platform/windows/OFPlainCondition.m +++ src/platform/windows/OFPlainCondition.m @@ -1,135 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#include - -#import "OFPlainCondition.h" - -#include - -int -OFPlainConditionNew(OFPlainCondition *condition) -{ - condition->count = 0; - - if ((condition->event = CreateEvent(NULL, FALSE, 0, NULL)) == NULL) - return EAGAIN; - - return 0; -} - -int -OFPlainConditionSignal(OFPlainCondition *condition) -{ - if (!SetEvent(condition->event)) { - switch (GetLastError()) { - case ERROR_INVALID_HANDLE: - return EINVAL; - default: - OFEnsure(0); - } - } - - return 0; -} - -int -OFPlainConditionBroadcast(OFPlainCondition *condition) -{ - int count = condition->count; - - for (int i = 0; i < count; i++) { - if (!SetEvent(condition->event)) { - switch (GetLastError()) { - case ERROR_INVALID_HANDLE: - return EINVAL; - default: - OFEnsure(0); - } - } - } - - return 0; -} - -int -OFPlainConditionWait(OFPlainCondition *condition, OFPlainMutex *mutex) -{ - int error; - DWORD status; - - if ((error = OFPlainMutexUnlock(mutex)) != 0) - return error; - - OFAtomicIntIncrease(&condition->count); - status = WaitForSingleObject(condition->event, INFINITE); - OFAtomicIntDecrease(&condition->count); - - switch (status) { - case WAIT_OBJECT_0: - return OFPlainMutexLock(mutex); - case WAIT_FAILED: - switch (GetLastError()) { - case ERROR_INVALID_HANDLE: - return EINVAL; - default: - OFEnsure(0); - } - default: - OFEnsure(0); - } -} - -int -OFPlainConditionTimedWait(OFPlainCondition *condition, OFPlainMutex *mutex, - OFTimeInterval timeout) -{ - int error; - DWORD status; - - if ((error = OFPlainMutexUnlock(mutex)) != 0) - return error; - - OFAtomicIntIncrease(&condition->count); - status = WaitForSingleObject(condition->event, timeout * 1000); - OFAtomicIntDecrease(&condition->count); - - switch (status) { - case WAIT_OBJECT_0: - return OFPlainMutexLock(mutex); - case WAIT_TIMEOUT: - return ETIMEDOUT; - case WAIT_FAILED: - switch (GetLastError()) { - case ERROR_INVALID_HANDLE: - return EINVAL; - default: - OFEnsure(0); - } - default: - OFEnsure(0); - } -} - -int -OFPlainConditionFree(OFPlainCondition *condition) -{ - if (condition->count != 0) - return EBUSY; - - return (CloseHandle(condition->event) ? 0 : EINVAL); -} DELETED src/platform/windows/OFPlainMutex.m Index: src/platform/windows/OFPlainMutex.m ================================================================== --- src/platform/windows/OFPlainMutex.m +++ src/platform/windows/OFPlainMutex.m @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#include - -#import "OFPlainMutex.h" - -#include - -int -OFPlainMutexNew(OFPlainMutex *mutex) -{ - InitializeCriticalSection(mutex); - - return 0; -} - -int -OFPlainMutexLock(OFPlainMutex *mutex) -{ - EnterCriticalSection(mutex); - - return 0; -} - -int -OFPlainMutexTryLock(OFPlainMutex *mutex) -{ - if (!TryEnterCriticalSection(mutex)) - return EBUSY; - - return 0; -} - -int -OFPlainMutexUnlock(OFPlainMutex *mutex) -{ - LeaveCriticalSection(mutex); - - return 0; -} - -int -OFPlainMutexFree(OFPlainMutex *mutex) -{ - DeleteCriticalSection(mutex); - - return 0; -} - -int -OFPlainRecursiveMutexNew(OFPlainRecursiveMutex *rmutex) -{ - return OFPlainMutexNew(rmutex); -} - -int -OFPlainRecursiveMutexLock(OFPlainRecursiveMutex *rmutex) -{ - return OFPlainMutexLock(rmutex); -} - -int -OFPlainRecursiveMutexTryLock(OFPlainRecursiveMutex *rmutex) -{ - return OFPlainMutexTryLock(rmutex); -} - -int -OFPlainRecursiveMutexUnlock(OFPlainRecursiveMutex *rmutex) -{ - return OFPlainMutexUnlock(rmutex); -} - -int -OFPlainRecursiveMutexFree(OFPlainRecursiveMutex *rmutex) -{ - return OFPlainMutexFree(rmutex); -} DELETED src/platform/windows/OFPlainThread.m Index: src/platform/windows/OFPlainThread.m ================================================================== --- src/platform/windows/OFPlainThread.m +++ src/platform/windows/OFPlainThread.m @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#include - -#import "OFPlainThread.h" - -#import "macros.h" - -#include - -struct ThreadContext { - void (*function)(id); - id object; -}; - -static WINAPI void -functionWrapper(struct ThreadContext *context) -{ - context->function(context->object); - - free(context); -} - -int -OFPlainThreadAttributesInit(OFPlainThreadAttributes *attr) -{ - attr->priority = 0; - attr->stackSize = 0; - - return 0; -} - -int -OFPlainThreadNew(OFPlainThread *thread, const char *name, void (*function)(id), - id object, const OFPlainThreadAttributes *attr) -{ - DWORD priority = THREAD_PRIORITY_NORMAL; - struct ThreadContext *context; - DWORD threadID; - - if (attr != NULL && attr->priority != 0) { - if (attr->priority < -1 || attr->priority > 1) - return EINVAL; - - if (attr->priority < 0) - priority = THREAD_PRIORITY_LOWEST + - (1.0 + attr->priority) * - (THREAD_PRIORITY_NORMAL - THREAD_PRIORITY_LOWEST); - else - priority = THREAD_PRIORITY_NORMAL + - attr->priority * - (THREAD_PRIORITY_HIGHEST - THREAD_PRIORITY_NORMAL); - } - - if ((context = malloc(sizeof(*context))) == NULL) - return ENOMEM; - - context->function = function; - context->object = object; - - *thread = CreateThread(NULL, (attr != NULL ? attr->stackSize : 0), - (LPTHREAD_START_ROUTINE)functionWrapper, context, 0, &threadID); - - if (thread == NULL) { - int error; - - switch (GetLastError()) { - case ERROR_NOT_ENOUGH_MEMORY: - error = ENOMEM; - break; - case ERROR_ACCESS_DENIED: - error = EACCES; - break; - default: - OFEnsure(0); - } - - free(context); - return error; - } - - if (attr != NULL && attr->priority != 0) - OFEnsure(!SetThreadPriority(*thread, priority)); - - return 0; -} - -int -OFPlainThreadJoin(OFPlainThread thread) -{ - switch (WaitForSingleObject(thread, INFINITE)) { - case WAIT_OBJECT_0: - CloseHandle(thread); - return 0; - case WAIT_FAILED: - switch (GetLastError()) { - case ERROR_INVALID_HANDLE: - return EINVAL; - default: - OFEnsure(0); - } - default: - OFEnsure(0); - } -} - -int -OFPlainThreadDetach(OFPlainThread thread) -{ - CloseHandle(thread); - - return 0; -} - -void -OFSetThreadName(const char *name) -{ -} DELETED src/platform/windows/OFString+PathAdditions.m Index: src/platform/windows/OFString+PathAdditions.m ================================================================== --- src/platform/windows/OFString+PathAdditions.m +++ src/platform/windows/OFString+PathAdditions.m @@ -1,382 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -/* - * This file is also used for MS-DOS! Don't forget to #ifdef Windows-specific - * parts! - */ - -#include "config.h" - -#import "OFString+PathAdditions.h" -#import "OFArray.h" -#import "OFFileURLHandler.h" -#import "OFURL.h" - -#import "OFInvalidFormatException.h" -#import "OFOutOfRangeException.h" - -int _OFString_PathAdditions_reference; - -@implementation OFString (PathAdditions) -+ (OFString *)pathWithComponents: (OFArray *)components -{ - OFMutableString *ret = [OFMutableString string]; - void *pool = objc_autoreleasePoolPush(); - bool first = true; - - for (OFString *component in components) { - if (component.length == 0) - continue; - - if (!first && ![ret hasSuffix: @":"] && - ([component isEqual: @"\\"] || [component isEqual: @"/"])) - continue; - - if (!first && ![ret hasSuffix: @"\\"] && - ![ret hasSuffix: @"/"] && ![ret hasSuffix: @":"]) - [ret appendString: @"\\"]; - - [ret appendString: component]; - - first = false; - } - - [ret makeImmutable]; - - objc_autoreleasePoolPop(pool); - - return ret; -} - -- (bool)isAbsolutePath -{ -#ifdef OF_WINDOWS - if ([self hasPrefix: @"\\\\"]) - return true; -#endif - - return ([self containsString: @":\\"] || [self containsString: @":/"]); -} - -- (OFArray *)pathComponents -{ - OFMutableArray OF_GENERIC(OFString *) *ret = [OFMutableArray array]; - void *pool = objc_autoreleasePoolPush(); - const char *cString = self.UTF8String; - size_t i, last = 0, cStringLength = self.UTF8StringLength; - bool isUNC = false; - - if (cStringLength == 0) { - objc_autoreleasePoolPop(pool); - return ret; - } - -#ifdef OF_WINDOWS - if ([self hasPrefix: @"\\\\"]) { - isUNC = true; - [ret addObject: @"\\\\"]; - - cString += 2; - cStringLength -= 2; - } -#endif - - for (i = 0; i < cStringLength; i++) { - if (cString[i] == '\\' || cString[i] == '/') { - if (i == 0) - [ret addObject: [OFString - stringWithUTF8String: cString - length: 1]]; - else if (i - last != 0) - [ret addObject: [OFString - stringWithUTF8String: cString + last - length: i - last]]; - - last = i + 1; - } else if (!isUNC && cString[i] == ':') { - if (i + 1 < cStringLength && - (cString[i + 1] == '\\' || cString[i + 1] == '/')) - i++; - - [ret addObject: [OFString - stringWithUTF8String: cString + last - length: i - last + 1]]; - - last = i + 1; - } - } - if (i - last != 0) - [ret addObject: [OFString stringWithUTF8String: cString + last - length: i - last]]; - - [ret makeImmutable]; - - objc_autoreleasePoolPop(pool); - - return ret; -} - -- (OFString *)lastPathComponent -{ - /* - * Windows/DOS need the full parsing to determine the last path - * component. This could be optimized by not creating the temporary - * objects, though. - */ - void *pool = objc_autoreleasePoolPush(); - OFString *ret = self.pathComponents.lastObject; - - if (ret == nil) { - objc_autoreleasePoolPop(pool); - return @""; - } - - [ret retain]; - objc_autoreleasePoolPop(pool); - return [ret autorelease]; -} - -- (OFString *)pathExtension -{ - void *pool = objc_autoreleasePoolPush(); - OFString *ret, *fileName; - size_t pos; - - fileName = self.lastPathComponent; - pos = [fileName rangeOfString: @"." - options: OFStringSearchBackwards].location; - if (pos == OFNotFound || pos == 0) { - objc_autoreleasePoolPop(pool); - return @""; - } - - ret = [fileName substringFromIndex: pos + 1]; - - [ret retain]; - objc_autoreleasePoolPop(pool); - return [ret autorelease]; -} - -- (OFString *)stringByDeletingLastPathComponent -{ - /* - * Windows/DOS need the full parsing to delete the last path component. - * This could be optimized, though. - */ - void *pool = objc_autoreleasePoolPush(); - OFArray OF_GENERIC(OFString *) *components = self.pathComponents; - size_t count = components.count; - OFString *ret; - - if (count == 0) { - objc_autoreleasePoolPop(pool); - return @""; - } - - if (count == 1) { - OFString *firstComponent = components.firstObject; - - if ([firstComponent hasSuffix: @":"] || - [firstComponent hasSuffix: @":\\"] || - [firstComponent hasSuffix: @":/"] || - [firstComponent hasPrefix: @"\\"]) { - ret = [firstComponent retain]; - objc_autoreleasePoolPop(pool); - return [ret autorelease]; - } - - objc_autoreleasePoolPop(pool); - return @"."; - } - - components = [components objectsInRange: - OFRangeMake(0, components.count - 1)]; - ret = [OFString pathWithComponents: components]; - - [ret retain]; - objc_autoreleasePoolPop(pool); - return [ret autorelease]; -} - -- (OFString *)stringByDeletingPathExtension -{ - void *pool; - OFMutableArray OF_GENERIC(OFString *) *components; - OFString *ret, *fileName; - size_t pos; - - if (self.length == 0) - return [[self copy] autorelease]; - - pool = objc_autoreleasePoolPush(); - components = [[self.pathComponents mutableCopy] autorelease]; - fileName = components.lastObject; - - pos = [fileName rangeOfString: @"." - options: OFStringSearchBackwards].location; - if (pos == OFNotFound || pos == 0) { - objc_autoreleasePoolPop(pool); - return [[self copy] autorelease]; - } - - fileName = [fileName substringToIndex: pos]; - [components replaceObjectAtIndex: components.count - 1 - withObject: fileName]; - - ret = [OFString pathWithComponents: components]; - - [ret retain]; - objc_autoreleasePoolPop(pool); - return [ret autorelease]; -} - -- (OFString *)stringByStandardizingPath -{ - void *pool = objc_autoreleasePoolPush(); - OFArray OF_GENERIC(OFString *) *components; - OFMutableArray OF_GENERIC(OFString *) *array; - OFString *ret; - bool done = false; - - if (self.length == 0) - return @""; - - components = self.pathComponents; - - if (components.count == 1) { - objc_autoreleasePoolPop(pool); - return [[self copy] autorelease]; - } - - array = [[components mutableCopy] autorelease]; - - while (!done) { - size_t length = array.count; - - done = true; - - for (size_t i = 0; i < length; i++) { - OFString *component = [array objectAtIndex: i]; - OFString *parent = - (i > 0 ? [array objectAtIndex: i - 1] : 0); - - if ([component isEqual: @"."] || - component.length == 0) { - [array removeObjectAtIndex: i]; - - done = false; - break; - } - - if ([component isEqual: @".."] && parent != nil && - ![parent isEqual: @".."] && - ![parent hasSuffix: @":"] && - ![parent hasSuffix: @":\\"] && - ![parent hasSuffix: @"://"] && - (![parent hasPrefix: @"\\"] || i != 1)) { - [array removeObjectsInRange: - OFRangeMake(i - 1, 2)]; - - done = false; - break; - } - } - } - - ret = [[OFString pathWithComponents: array] retain]; - - objc_autoreleasePoolPop(pool); - - return [ret autorelease]; -} - -- (OFString *)stringByAppendingPathComponent: (OFString *)component -{ - if ([self hasSuffix: @"\\"] || [self hasSuffix: @"/"]) - return [self stringByAppendingString: component]; - else { - OFMutableString *ret = [[self mutableCopy] autorelease]; - - [ret appendString: @"\\"]; - [ret appendString: component]; - - [ret makeImmutable]; - - return ret; - } -} - -- (bool)of_isDirectoryPath -{ - return ([self hasSuffix: @"\\"] || [self hasSuffix: @"/"] || - [OFFileURLHandler of_directoryExistsAtPath: self]); -} - -- (OFString *)of_pathToURLPathWithURLEncodedHost: (OFString **)URLEncodedHost -{ - OFString *path = self; - - if ([path hasPrefix: @"\\\\"]) { - OFArray *components = path.pathComponents; - - if (components.count < 2) - @throw [OFInvalidFormatException exception]; - - *URLEncodedHost = [[components objectAtIndex: 1] - stringByURLEncodingWithAllowedCharacters: - [OFCharacterSet URLHostAllowedCharacterSet]]; - path = [OFString pathWithComponents: [components - objectsInRange: OFRangeMake(2, components.count - 2)]]; - } - - path = [path stringByReplacingOccurrencesOfString: @"\\" - withString: @"/"]; - path = [path stringByPrependingString: @"/"]; - - return path; -} - -- (OFString *)of_URLPathToPathWithURLEncodedHost: (OFString *)URLEncodedHost -{ - OFString *path = self; - - if (path.length > 1 && [path hasSuffix: @"/"] && - ![path hasSuffix: @":/"]) - path = [path substringToIndex: path.length - 1]; - - path = [path substringFromIndex: 1]; - path = [path stringByReplacingOccurrencesOfString: @"/" - withString: @"\\"]; - - if (URLEncodedHost != nil) { - OFString *host = [URLEncodedHost stringByURLDecoding]; - - if (path.length == 0) - path = [OFString stringWithFormat: @"\\\\%@", host]; - else - path = [OFString stringWithFormat: @"\\\\%@\\%@", - host, path]; - } - - return path; -} - -- (OFString *)of_pathComponentToURLPathComponent -{ - return [self stringByReplacingOccurrencesOfString: @"\\" - withString: @"/"]; -} -@end DELETED src/platform/windows/OFSubprocess.m Index: src/platform/windows/OFSubprocess.m ================================================================== --- src/platform/windows/OFSubprocess.m +++ src/platform/windows/OFSubprocess.m @@ -1,419 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#include -#include - -#import "OFSubprocess.h" -#import "OFArray.h" -#import "OFData.h" -#import "OFDictionary.h" -#import "OFLocale.h" -#import "OFString.h" -#import "OFSystemInfo.h" - -#import "OFInitializationFailedException.h" -#import "OFNotOpenException.h" -#import "OFOutOfRangeException.h" -#import "OFReadFailedException.h" -#import "OFWriteFailedException.h" - -#include - -@interface OFSubprocess () -- (OFChar16 *)of_wideEnvironmentForDictionary: (OFDictionary *)dictionary; -- (char *)of_environmentForDictionary: (OFDictionary *)environment; -@end - -@implementation OFSubprocess -+ (instancetype)subprocessWithProgram: (OFString *)program -{ - return [[[self alloc] initWithProgram: program] autorelease]; -} - -+ (instancetype)subprocessWithProgram: (OFString *)program - arguments: (OFArray *)arguments -{ - return [[[self alloc] initWithProgram: program - arguments: arguments] autorelease]; -} - -+ (instancetype)subprocessWithProgram: (OFString *)program - programName: (OFString *)programName - arguments: (OFArray *)arguments -{ - return [[[self alloc] initWithProgram: program - programName: programName - arguments: arguments] autorelease]; -} - -+ (instancetype)subprocessWithProgram: (OFString *)program - programName: (OFString *)programName - arguments: (OFArray *)arguments - environment: (OFDictionary *)environment -{ - return [[[self alloc] initWithProgram: program - programName: programName - arguments: arguments - environment: environment] autorelease]; -} - -- (instancetype)init -{ - OF_INVALID_INIT_METHOD -} - -- (instancetype)initWithProgram: (OFString *)program -{ - return [self initWithProgram: program - programName: program - arguments: nil - environment: nil]; -} - -- (instancetype)initWithProgram: (OFString *)program - arguments: (OFArray *)arguments -{ - return [self initWithProgram: program - programName: program - arguments: arguments - environment: nil]; -} - -- (instancetype)initWithProgram: (OFString *)program - programName: (OFString *)programName - arguments: (OFArray *)arguments -{ - return [self initWithProgram: program - programName: program - arguments: arguments - environment: nil]; -} - -- (instancetype)initWithProgram: (OFString *)program - programName: (OFString *)programName - arguments: (OFArray *)arguments - environment: (OFDictionary *)environment -{ - self = [super init]; - - @try { - SECURITY_ATTRIBUTES sa; - PROCESS_INFORMATION pi; - void *pool; - OFMutableString *argumentsString; - - _handle = INVALID_HANDLE_VALUE; - _readPipe[0] = _writePipe[1] = NULL; - - sa.nLength = sizeof(sa); - sa.bInheritHandle = TRUE; - sa.lpSecurityDescriptor = NULL; - - if (!CreatePipe(&_readPipe[0], &_readPipe[1], &sa, 0)) - @throw [OFInitializationFailedException - exceptionWithClass: self.class]; - - if (!SetHandleInformation(_readPipe[0], HANDLE_FLAG_INHERIT, 0)) - if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) - @throw [OFInitializationFailedException - exceptionWithClass: self.class]; - - if (!CreatePipe(&_writePipe[0], &_writePipe[1], &sa, 0)) - @throw [OFInitializationFailedException - exceptionWithClass: self.class]; - - if (!SetHandleInformation(_writePipe[1], - HANDLE_FLAG_INHERIT, 0)) - if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) - @throw [OFInitializationFailedException - exceptionWithClass: self.class]; - - memset(&pi, 0, sizeof(pi)); - - pool = objc_autoreleasePoolPush(); - - argumentsString = - [OFMutableString stringWithString: programName]; - [argumentsString replaceOccurrencesOfString: @"\\\"" - withString: @"\\\\\""]; - [argumentsString replaceOccurrencesOfString: @"\"" - withString: @"\\\""]; - - if ([argumentsString containsString: @" "]) { - [argumentsString prependString: @"\""]; - [argumentsString appendString: @"\""]; - } - - for (OFString *argument in arguments) { - OFMutableString *tmp = - [[argument mutableCopy] autorelease]; - bool containsSpaces = [tmp containsString: @" "]; - - [argumentsString appendString: @" "]; - - if (containsSpaces) - [argumentsString appendString: @"\""]; - - [tmp replaceOccurrencesOfString: @"\\\"" - withString: @"\\\\\""]; - [tmp replaceOccurrencesOfString: @"\"" - withString: @"\\\""]; - - [argumentsString appendString: tmp]; - - if (containsSpaces) - [argumentsString appendString: @"\""]; - } - - if ([OFSystemInfo isWindowsNT]) { - size_t length; - OFChar16 *argumentsCopy; - STARTUPINFOW si; - - memset(&si, 0, sizeof(si)); - si.cb = sizeof(si); - si.hStdInput = _writePipe[0]; - si.hStdOutput = _readPipe[1]; - si.hStdError = GetStdHandle(STD_ERROR_HANDLE); - si.dwFlags |= STARTF_USESTDHANDLES; - - length = argumentsString.UTF16StringLength; - argumentsCopy = OFAllocMemory(length + 1, - sizeof(OFChar16)); - memcpy(argumentsCopy, argumentsString.UTF16String, - (length + 1) * 2); - @try { - if (!CreateProcessW(program.UTF16String, - argumentsCopy, NULL, NULL, TRUE, - CREATE_UNICODE_ENVIRONMENT, - [self of_wideEnvironmentForDictionary: - environment], NULL, &si, &pi)) - @throw [OFInitializationFailedException - exceptionWithClass: self.class]; - } @finally { - OFFreeMemory(argumentsCopy); - } - } else { - OFStringEncoding encoding = [OFLocale encoding]; - STARTUPINFO si; - - memset(&si, 0, sizeof(si)); - si.cb = sizeof(si); - si.hStdInput = _writePipe[0]; - si.hStdOutput = _readPipe[1]; - si.hStdError = GetStdHandle(STD_ERROR_HANDLE); - si.dwFlags |= STARTF_USESTDHANDLES; - - if (!CreateProcessA([program cStringWithEncoding: - encoding], (char *)[argumentsString - cStringWithEncoding: encoding], NULL, NULL, TRUE, 0, - [self of_environmentForDictionary: environment], - NULL, &si, &pi)) - @throw [OFInitializationFailedException - exceptionWithClass: self.class]; - } - - objc_autoreleasePoolPop(pool); - - _handle = pi.hProcess; - CloseHandle(pi.hThread); - - CloseHandle(_readPipe[1]); - CloseHandle(_writePipe[0]); - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)dealloc -{ - if (_readPipe[0] != NULL) - [self close]; - - [super dealloc]; -} - -- (OFChar16 *)of_wideEnvironmentForDictionary: (OFDictionary *)environment -{ - OFMutableData *env; - OFEnumerator *keyEnumerator, *objectEnumerator; - OFString *key, *object; - const OFChar16 equal = '='; - const OFChar16 zero[2] = { 0, 0 }; - - if (environment == nil) - return NULL; - - env = [OFMutableData dataWithItemSize: sizeof(OFChar16)]; - - keyEnumerator = [environment keyEnumerator]; - objectEnumerator = [environment objectEnumerator]; - while ((key = [keyEnumerator nextObject]) != nil && - (object = [objectEnumerator nextObject]) != nil) { - [env addItems: key.UTF16String count: key.UTF16StringLength]; - [env addItems: &equal count: 1]; - [env addItems: object.UTF16String - count: object.UTF16StringLength]; - [env addItems: &zero count: 1]; - } - [env addItems: zero count: 2]; - - return env.mutableItems; -} - -- (char *)of_environmentForDictionary: (OFDictionary *)environment -{ - OFStringEncoding encoding = [OFLocale encoding]; - OFMutableData *env; - OFEnumerator *keyEnumerator, *objectEnumerator; - OFString *key, *object; - - if (environment == nil) - return NULL; - - env = [OFMutableData data]; - - keyEnumerator = [environment keyEnumerator]; - objectEnumerator = [environment objectEnumerator]; - while ((key = [keyEnumerator nextObject]) != nil && - (object = [objectEnumerator nextObject]) != nil) { - [env addItems: [key cStringWithEncoding: encoding] - count: [key cStringLengthWithEncoding: encoding]]; - [env addItems: "=" count: 1]; - [env addItems: [object cStringWithEncoding: encoding] - count: [object cStringLengthWithEncoding: encoding]]; - [env addItems: "" count: 1]; - } - [env addItems: "\0" count: 2]; - - return env.mutableItems; -} - -- (bool)lowlevelIsAtEndOfStream -{ - if (_readPipe[0] == NULL) - @throw [OFNotOpenException exceptionWithObject: self]; - - return _atEndOfStream; -} - -- (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)length -{ - DWORD ret; - - if (length > UINT32_MAX) - @throw [OFOutOfRangeException exception]; - - if (_readPipe[0] == NULL) - @throw [OFNotOpenException exceptionWithObject: self]; - - if (!ReadFile(_readPipe[0], buffer, (DWORD)length, &ret, NULL)) { - if (GetLastError() == ERROR_BROKEN_PIPE) { - _atEndOfStream = true; - return 0; - } - - @throw [OFReadFailedException exceptionWithObject: self - requestedLength: length - errNo: EIO]; - } - - if (ret == 0) - _atEndOfStream = true; - - return ret; -} - -- (size_t)lowlevelWriteBuffer: (const void *)buffer length: (size_t)length -{ - DWORD bytesWritten; - - if (length > UINT32_MAX) - @throw [OFOutOfRangeException exception]; - - if (_writePipe[1] == NULL) - @throw [OFNotOpenException exceptionWithObject: self]; - - if (!WriteFile(_writePipe[1], buffer, (DWORD)length, &bytesWritten, - NULL)) { - int errNo = EIO; - - if (GetLastError() == ERROR_BROKEN_PIPE) - errNo = EPIPE; - - @throw [OFWriteFailedException exceptionWithObject: self - requestedLength: length - bytesWritten: 0 - errNo: errNo]; - } - - return (size_t)bytesWritten; -} - -- (void)closeForWriting -{ - if (_writePipe[1] != NULL) - CloseHandle(_writePipe[1]); - - _writePipe[1] = NULL; -} - -- (void)close -{ - if (_readPipe[0] == NULL) - @throw [OFNotOpenException exceptionWithObject: self]; - - [self closeForWriting]; - CloseHandle(_readPipe[0]); - - if (_handle != INVALID_HANDLE_VALUE) { - TerminateProcess(_handle, 0); - CloseHandle(_handle); - } - - _handle = INVALID_HANDLE_VALUE; - _readPipe[0] = NULL; - - [super close]; -} - -- (int)waitForTermination -{ - if (_readPipe[0] == NULL) - @throw [OFNotOpenException exceptionWithObject: self]; - - if (_handle != INVALID_HANDLE_VALUE) { - DWORD exitCode; - - WaitForSingleObject(_handle, INFINITE); - - if (GetExitCodeProcess(_handle, &exitCode)) - _status = exitCode; - else - _status = GetLastError(); - - CloseHandle(_handle); - _handle = INVALID_HANDLE_VALUE; - } - - return _status; -} -@end DELETED src/platform/windows/OFTLSKey.m Index: src/platform/windows/OFTLSKey.m ================================================================== --- src/platform/windows/OFTLSKey.m +++ src/platform/windows/OFTLSKey.m @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#import "OFTLSKey.h" - -int -OFTLSKeyNew(OFTLSKey *key) -{ - *key = TlsAlloc(); - - if (*key == TLS_OUT_OF_INDEXES) - return EAGAIN; - - return 0; -} - -int -OFTLSKeyFree(OFTLSKey key) -{ - return (TlsFree(key) ? 0 : EINVAL); -} ADDED src/platform/x86/OFAtomic.h Index: src/platform/x86/OFAtomic.h ================================================================== --- src/platform/x86/OFAtomic.h +++ src/platform/x86/OFAtomic.h @@ -0,0 +1,502 @@ +/* + * Copyright (c) 2008-2021 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +OF_ASSUME_NONNULL_BEGIN + +static OF_INLINE int +OFAtomicIntAdd(volatile int *_Nonnull p, int i) +{ + if (sizeof(int) == 4) + __asm__ __volatile__ ( + "lock\n\t" + "xaddl %0, %2\n\t" + "addl %1, %0" + : "+&r"(i) + : "r"(i), "m"(*p) + ); +#ifdef OF_X86_64 + else if (sizeof(int) == 8) + __asm__ __volatile__ ( + "lock\n\t" + "xaddq %0, %2\n\t" + "addq %1, %0" + : "+&r"(i) + : "r"(i), "m"(*p) + ); +#endif + else + abort(); + + return i; +} + +static OF_INLINE int32_t +OFAtomicInt32Add(volatile int32_t *_Nonnull p, int32_t i) +{ + __asm__ __volatile__ ( + "lock\n\t" + "xaddl %0, %2\n\t" + "addl %1, %0" + : "+&r"(i) + : "r"(i), "m"(*p) + ); + + return i; +} + +static OF_INLINE void *_Nullable +OFAtomicPointerAdd(void *volatile _Nullable *_Nonnull p, intptr_t i) +{ +#if defined(OF_X86_64) + __asm__ __volatile__ ( + "lock\n\t" + "xaddq %0, %2\n\t" + "addq %1, %0" + : "+&r"(i) + : "r"(i), "m"(*p) + ); + + return (void *)i; +#elif defined(OF_X86) + __asm__ __volatile__ ( + "lock\n\t" + "xaddl %0, %2\n\t" + "addl %1, %0" + : "+&r"(i) + : "r"(i), "m"(*p) + ); + + return (void *)i; +#endif +} + +static OF_INLINE int +OFAtomicIntSubtract(volatile int *_Nonnull p, int i) +{ + if (sizeof(int) == 4) + __asm__ __volatile__ ( + "negl %0\n\t" + "lock\n\t" + "xaddl %0, %2\n\t" + "subl %1, %0" + : "+&r"(i) + : "r"(i), "m"(*p) + ); +#ifdef OF_X86_64 + else if (sizeof(int) == 8) + __asm__ __volatile__ ( + "negq %0\n\t" + "lock\n\t" + "xaddq %0, %2\n\t" + "subq %1, %0" + : "+&r"(i) + : "r"(i), "m"(*p) + ); +#endif + else + abort(); + + return i; +} + +static OF_INLINE int32_t +OFAtomicInt32Subtract(volatile int32_t *_Nonnull p, int32_t i) +{ + __asm__ __volatile__ ( + "negl %0\n\t" + "lock\n\t" + "xaddl %0, %2\n\t" + "subl %1, %0" + : "+&r"(i) + : "r"(i), "m"(*p) + ); + + return i; +} + +static OF_INLINE void *_Nullable +OFAtomicPointerSubtract(void *volatile _Nullable *_Nonnull p, intptr_t i) +{ +#if defined(OF_X86_64) + __asm__ __volatile__ ( + "negq %0\n\t" + "lock\n\t" + "xaddq %0, %2\n\t" + "subq %1, %0" + : "+&r"(i) + : "r"(i), "m"(*p) + ); + + return (void *)i; +#elif defined(OF_X86) + __asm__ __volatile__ ( + "negl %0\n\t" + "lock\n\t" + "xaddl %0, %2\n\t" + "subl %1, %0" + : "+&r"(i) + : "r"(i), "m"(*p) + ); + + return (void *)i; +#endif +} + +static OF_INLINE int +OFAtomicIntIncrease(volatile int *_Nonnull p) +{ + int i; + + if (sizeof(int) == 4) + __asm__ __volatile__ ( + "xorl %0, %0\n\t" + "incl %0\n\t" + "lock\n\t" + "xaddl %0, %1\n\t" + "incl %0" + : "=&r"(i) + : "m"(*p) + ); +#ifdef OF_X86_64 + else if (sizeof(int) == 8) + __asm__ __volatile__ ( + "xorq %0, %0\n\t" + "incq %0\n\t" + "lock\n\t" + "xaddq %0, %1\n\t" + "incq %0" + : "=&r"(i) + : "m"(*p) + ); +#endif + else + abort(); + + return i; +} + +static OF_INLINE int32_t +OFAtomicInt32Increase(volatile int32_t *_Nonnull p) +{ + int32_t i; + + __asm__ __volatile__ ( + "xorl %0, %0\n\t" + "incl %0\n\t" + "lock\n\t" + "xaddl %0, %1\n\t" + "incl %0" + : "=&r"(i) + : "m"(*p) + ); + + return i; +} + +static OF_INLINE int +OFAtomicIntDecrease(volatile int *_Nonnull p) +{ + int i; + + if (sizeof(int) == 4) + __asm__ __volatile__ ( + "xorl %0, %0\n\t" + "decl %0\n\t" + "lock\n\t" + "xaddl %0, %1\n\t" + "decl %0" + : "=&r"(i) + : "m"(*p) + ); +#ifdef OF_X86_64 + else if (sizeof(int) == 8) + __asm__ __volatile__ ( + "xorq %0, %0\n\t" + "decq %0\n\t" + "lock\n\t" + "xaddq %0, %1\n\t" + "decq %0" + : "=&r"(i) + : "m"(*p) + ); +#endif + else + abort(); + + return i; +} + +static OF_INLINE int32_t +OFAtomicInt32Decrease(volatile int32_t *_Nonnull p) +{ + int32_t i; + + __asm__ __volatile__ ( + "xorl %0, %0\n\t" + "decl %0\n\t" + "lock\n\t" + "xaddl %0, %1\n\t" + "decl %0" + : "=&r"(i) + : "m"(*p) + ); + + return i; +} + +static OF_INLINE unsigned int +OFAtomicIntOr(volatile unsigned int *_Nonnull p, unsigned int i) +{ + if (sizeof(int) == 4) + __asm__ __volatile__ ( + "0:\n\t" + "movl %2, %0\n\t" + "movl %0, %%eax\n\t" + "orl %1, %0\n\t" + "lock\n\t" + "cmpxchg %0, %2\n\t" + "jne 0b" + : "=&r"(i) + : "r"(i), "m"(*p) + : "eax", "cc" + ); +#ifdef OF_X86_64 + else if (sizeof(int) == 8) + __asm__ __volatile__ ( + "0:\n\t" + "movq %2, %0\n\t" + "movq %0, %%rax\n\t" + "orq %1, %0\n\t" + "lock\n\t" + "cmpxchg %0, %2\n\t" + "jne 0b" + : "=&r"(i) + : "r"(i), "m"(*p) + : "rax", "cc" + ); +#endif + else + abort(); + + return i; +} + +static OF_INLINE uint32_t +OFAtomicInt32Or(volatile uint32_t *_Nonnull p, uint32_t i) +{ + __asm__ __volatile__ ( + "0:\n\t" + "movl %2, %0\n\t" + "movl %0, %%eax\n\t" + "orl %1, %0\n\t" + "lock\n\t" + "cmpxchg %0, %2\n\t" + "jne 0b" + : "=&r"(i) + : "r"(i), "m"(*p) + : "eax", "cc" + ); + + return i; +} + +static OF_INLINE unsigned int +OFAtomicIntAnd(volatile unsigned int *_Nonnull p, unsigned int i) +{ + if (sizeof(int) == 4) + __asm__ __volatile__ ( + "0:\n\t" + "movl %2, %0\n\t" + "movl %0, %%eax\n\t" + "andl %1, %0\n\t" + "lock\n\t" + "cmpxchg %0, %2\n\t" + "jne 0b" + : "=&r"(i) + : "r"(i), "m"(*p) + : "eax", "cc" + ); +#ifdef OF_X86_64 + else if (sizeof(int) == 8) + __asm__ __volatile__ ( + "0:\n\t" + "movq %2, %0\n\t" + "movq %0, %%rax\n\t" + "andq %1, %0\n\t" + "lock\n\t" + "cmpxchg %0, %2\n\t" + "jne 0b" + : "=&r"(i) + : "r"(i), "m"(*p) + : "rax", "cc" + ); +#endif + else + abort(); + + return i; +} + +static OF_INLINE uint32_t +OFAtomicInt32And(volatile uint32_t *_Nonnull p, uint32_t i) +{ + __asm__ __volatile__ ( + "0:\n\t" + "movl %2, %0\n\t" + "movl %0, %%eax\n\t" + "andl %1, %0\n\t" + "lock\n\t" + "cmpxchg %0, %2\n\t" + "jne 0b" + : "=&r"(i) + : "r"(i), "m"(*p) + : "eax", "cc" + ); + + return i; +} + +static OF_INLINE unsigned int +OFAtomicIntXor(volatile unsigned int *_Nonnull p, unsigned int i) +{ + if (sizeof(int) == 4) + __asm__ __volatile__ ( + "0:\n\t" + "movl %2, %0\n\t" + "movl %0, %%eax\n\t" + "xorl %1, %0\n\t" + "lock\n\t" + "cmpxchg %0, %2\n\t" + "jne 0b" + : "=&r"(i) + : "r"(i), "m"(*p) + : "eax", "cc" + ); +#ifdef OF_X86_64 + else if (sizeof(int) == 8) + __asm__ __volatile__ ( + "0:\n\t" + "movq %2, %0\n\t" + "movq %0, %%rax\n\t" + "xorq %1, %0\n\t" + "lock\n\t" + "cmpxchg %0, %2\n\t" + "jne 0b" + : "=&r"(i) + : "r"(i), "m"(*p) + : "rax", "cc" + ); +#endif + else + abort(); + + return i; +} + +static OF_INLINE uint32_t +OFAtomicInt32Xor(volatile uint32_t *_Nonnull p, uint32_t i) +{ + __asm__ __volatile__ ( + "0:\n\t" + "movl %2, %0\n\t" + "movl %0, %%eax\n\t" + "xorl %1, %0\n\t" + "lock\n\t" + "cmpxchgl %0, %2\n\t" + "jne 0b" + : "=&r"(i) + : "r"(i), "m"(*p) + : "eax", "cc" + ); + + return i; +} + +static OF_INLINE bool +OFAtomicIntCompareAndSwap(volatile int *_Nonnull p, int o, int n) +{ + int r; + + __asm__ __volatile__ ( + "lock\n\t" + "cmpxchg %2, %3\n\t" + "sete %b0\n\t" + "movzbl %b0, %0" + : "=&d"(r), "+a"(o) /* use d instead of r to avoid a gcc bug */ + : "r"(n), "m"(*p) + : "cc" + ); + + return r; +} + +static OF_INLINE bool +OFAtomicInt32CompareAndSwap(volatile int32_t *_Nonnull p, int32_t o, int32_t n) +{ + int r; + + __asm__ __volatile__ ( + "lock\n\t" + "cmpxchg %2, %3\n\t" + "sete %b0\n\t" + "movzbl %b0, %0" + : "=&d"(r), "+a"(o) /* use d instead of r to avoid a gcc bug */ + : "r"(n), "m"(*p) + : "cc" + ); + + return r; +} + +static OF_INLINE bool +OFAtomicPointerCompareAndSwap(void *volatile _Nullable *_Nonnull p, + void *_Nullable o, void *_Nullable n) +{ + int r; + + __asm__ __volatile__ ( + "lock\n\t" + "cmpxchg %2, %3\n\t" + "sete %b0\n\t" + "movzbl %b0, %0" + : "=&d"(r), "+a"(o) /* use d instead of r to avoid a gcc bug */ + : "r"(n), "m"(*p) + : "cc" + ); + + return r; +} + +static OF_INLINE void +OFMemoryBarrier(void) +{ + __asm__ __volatile__ ( + "mfence" ::: "memory" + ); +} + +static OF_INLINE void +OFAcquireMemoryBarrier(void) +{ + __asm__ __volatile__ ("" ::: "memory"); +} + +static OF_INLINE void +OFReleaseMemoryBarrier(void) +{ + __asm__ __volatile__ ("" ::: "memory"); +} + +OF_ASSUME_NONNULL_END Index: src/runtime/ObjFWRT.h ================================================================== --- src/runtime/ObjFWRT.h +++ src/runtime/ObjFWRT.h @@ -144,18 +144,18 @@ /** * @brief A handler for uncaught exceptions. * * @param exception The exception which was not caught. */ -typedef void (*objc_uncaught_exception_handler_t)(id _Nullable exception); +typedef void (*objc_uncaught_exception_handler)(id _Nullable exception); /** * @brief A handler for mutation during enumeration. * * @param object The object that was mutated during enumeration */ -typedef void (*objc_enumeration_mutation_handler_t)(id _Nonnull object); +typedef void (*objc_enumeration_mutation_handler)(id _Nonnull object); /** * @brief A struct representing a call to super. */ struct objc_super { @@ -518,27 +518,27 @@ */ extern char *_Nullable property_copyAttributeValue( objc_property_t _Nonnull property, const char *_Nonnull name); /** - * @brief Exits the Objective-C runtime. + * @brief Deinitializes the Objective-C runtime. * * This frees all data structures used by the runtime, after which Objective-C * can no longer be used inside the current process. This is only useful for - * debugging. + * debugging and tests. */ -extern void objc_exit(void); +extern void objc_deinit(void); /** * @brief Sets the handler for uncaught exceptions. * * @param handler The new handler for uncaught exceptions * @return The old handler for uncaught exceptions */ -extern _Nullable objc_uncaught_exception_handler_t +extern _Nullable objc_uncaught_exception_handler objc_setUncaughtExceptionHandler( - objc_uncaught_exception_handler_t _Nullable handler); + objc_uncaught_exception_handler _Nullable handler); /** * @brief Sets the forwarding handler for unimplemented methods. * * @param forward The forwarding handler for regular methods @@ -552,11 +552,11 @@ * @brief Sets the handler for mutations during enumeration. * * @param handler The handler for mutations during enumeration */ extern void objc_setEnumerationMutationHandler( - objc_enumeration_mutation_handler_t _Nullable handler); + objc_enumeration_mutation_handler _Nullable handler); /** * @brief Constructs an instance of the specified class in the specified array * of bytes. * Index: src/runtime/amiga-funcarray.inc ================================================================== --- src/runtime/amiga-funcarray.inc +++ src/runtime/amiga-funcarray.inc @@ -11,11 +11,11 @@ * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ -/* This file is automatically generated from library.xml */ +/* This file is automatically generated from amiga-library.xml */ (CONST_APTR)glue_objc_init, (CONST_APTR)glue___objc_exec_class, (CONST_APTR)glue_objc_msg_lookup, (CONST_APTR)glue_objc_msg_lookup_stret, @@ -77,11 +77,11 @@ (CONST_APTR)glue_protocol_conformsToProtocol, (CONST_APTR)glue_objc_setUncaughtExceptionHandler, (CONST_APTR)glue_objc_setForwardHandler, (CONST_APTR)glue_objc_setEnumerationMutationHandler, (CONST_APTR)glue_objc_constructInstance, -(CONST_APTR)glue_objc_exit, +(CONST_APTR)glue_objc_deinit, (CONST_APTR)glue_class_copyIvarList, (CONST_APTR)glue_ivar_getName, (CONST_APTR)glue_ivar_getTypeEncoding, (CONST_APTR)glue_ivar_getOffset, (CONST_APTR)glue_class_copyMethodList, Index: src/runtime/amiga-glue.h ================================================================== --- src/runtime/amiga-glue.h +++ src/runtime/amiga-glue.h @@ -11,11 +11,11 @@ * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ -/* This file is automatically generated from library.xml */ +/* This file is automatically generated from amiga-library.xml */ #import "ObjFWRT.h" #import "private.h" #ifdef OF_AMIGAOS_M68K @@ -86,15 +86,15 @@ extern Class _Nullable glue_object_setClass PPC_PARAMS(id _Nullable object, Class _Nonnull class); extern const char *_Nullable glue_object_getClassName PPC_PARAMS(id _Nullable object); extern const char *_Nonnull glue_protocol_getName PPC_PARAMS(Protocol *_Nonnull protocol); extern bool glue_protocol_isEqual PPC_PARAMS(Protocol *_Nonnull protocol1, Protocol *_Nonnull protocol2); extern bool glue_protocol_conformsToProtocol PPC_PARAMS(Protocol *_Nonnull protocol1, Protocol *_Nonnull protocol2); -extern _Nullable objc_uncaught_exception_handler_t glue_objc_setUncaughtExceptionHandler PPC_PARAMS(objc_uncaught_exception_handler_t _Nullable handler); +extern _Nullable objc_uncaught_exception_handler glue_objc_setUncaughtExceptionHandler PPC_PARAMS(objc_uncaught_exception_handler _Nullable handler); extern void glue_objc_setForwardHandler PPC_PARAMS(IMP _Nullable forward, IMP _Nullable stretForward); -extern void glue_objc_setEnumerationMutationHandler PPC_PARAMS(objc_enumeration_mutation_handler_t _Nullable hadler); +extern void glue_objc_setEnumerationMutationHandler PPC_PARAMS(objc_enumeration_mutation_handler _Nullable hadler); extern id _Nullable glue_objc_constructInstance PPC_PARAMS(Class _Nullable class, void *_Nullable bytes); -extern void glue_objc_exit(void); +extern void glue_objc_deinit(void); extern Ivar _Nullable *_Nullable glue_class_copyIvarList PPC_PARAMS(Class _Nullable class, unsigned int *_Nullable outCount); extern const char *_Nonnull glue_ivar_getName PPC_PARAMS(Ivar _Nonnull ivar); extern const char *_Nonnull glue_ivar_getTypeEncoding PPC_PARAMS(Ivar _Nonnull ivar); extern ptrdiff_t glue_ivar_getOffset PPC_PARAMS(Ivar _Nonnull ivar); extern Method _Nullable *_Nullable glue_class_copyMethodList PPC_PARAMS(Class _Nullable class, unsigned int *_Nullable outCount); Index: src/runtime/amiga-glue.m ================================================================== --- src/runtime/amiga-glue.m +++ src/runtime/amiga-glue.m @@ -11,11 +11,11 @@ * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ -/* This file is automatically generated from library.xml */ +/* This file is automatically generated from amiga-library.xml */ #include "config.h" #import "amiga-glue.h" @@ -556,14 +556,14 @@ M68K_ARG(Protocol *_Nonnull, protocol2, a1) return protocol_conformsToProtocol(protocol1, protocol2); } -_Nullable objc_uncaught_exception_handler_t __saveds -glue_objc_setUncaughtExceptionHandler PPC_PARAMS(objc_uncaught_exception_handler_t _Nullable handler) +_Nullable objc_uncaught_exception_handler __saveds +glue_objc_setUncaughtExceptionHandler PPC_PARAMS(objc_uncaught_exception_handler _Nullable handler) { - M68K_ARG(objc_uncaught_exception_handler_t _Nullable, handler, a0) + M68K_ARG(objc_uncaught_exception_handler _Nullable, handler, a0) return objc_setUncaughtExceptionHandler(handler); } void __saveds @@ -574,13 +574,13 @@ objc_setForwardHandler(forward, stretForward); } void __saveds -glue_objc_setEnumerationMutationHandler PPC_PARAMS(objc_enumeration_mutation_handler_t _Nullable hadler) +glue_objc_setEnumerationMutationHandler PPC_PARAMS(objc_enumeration_mutation_handler _Nullable hadler) { - M68K_ARG(objc_enumeration_mutation_handler_t _Nullable, hadler, a0) + M68K_ARG(objc_enumeration_mutation_handler _Nullable, hadler, a0) objc_setEnumerationMutationHandler(hadler); } id _Nullable __saveds @@ -591,13 +591,13 @@ return objc_constructInstance(class, bytes); } void __saveds -glue_objc_exit(void) +glue_objc_deinit(void) { - objc_exit(); + objc_deinit(); } Ivar _Nullable *_Nullable __saveds glue_class_copyIvarList PPC_PARAMS(Class _Nullable class, unsigned int *_Nullable outCount) { ADDED src/runtime/amiga-library.xml Index: src/runtime/amiga-library.xml ================================================================== --- src/runtime/amiga-library.xml +++ src/runtime/amiga-library.xml @@ -0,0 +1,345 @@ + + ObjFWRT.h + private.h + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DELETED src/runtime/amigaos3.sfd Index: src/runtime/amigaos3.sfd ================================================================== --- src/runtime/amigaos3.sfd +++ src/runtime/amigaos3.sfd @@ -1,98 +0,0 @@ -==base _ObjFWRTBase -==basetype struct Library * -==libname objfwrt68k.library -==bias 30 -==public -* The following function is only for the linklib. -bool glue_objc_init(unsigned int version, struct objc_libc *libc)(d0,a0) -void glue___objc_exec_class(struct objc_module *_Nonnull module)(a0) -IMP _Nonnull glue_objc_msg_lookup(id _Nullable object, SEL _Nonnull selector)(a0,a1) -IMP _Nonnull glue_objc_msg_lookup_stret(id _Nullable object, SEL _Nonnull selector)(a0,a1) -IMP _Nonnull glue_objc_msg_lookup_super(struct objc_super *_Nonnull super, SEL _Nonnull selector)(a0,a1) -IMP _Nonnull glue_objc_msg_lookup_super_stret(struct objc_super *_Nonnull super, SEL _Nonnull selector)(a0,a1) -Class _Nullable glue_objc_lookUpClass(const char *_Nonnull name)(a0) -Class _Nullable glue_objc_getClass(const char *_Nonnull name)(a0) -Class _Nonnull glue_objc_getRequiredClass(const char *_Nonnull name)(a0) -Class _Nullable glue_objc_lookup_class(const char *_Nonnull name)(a0) -Class _Nonnull glue_objc_get_class(const char *_Nonnull name)(a0) -void glue_objc_exception_throw(id _Nonnull object)(a0) -int glue_objc_sync_enter(id _Nullable object)(a0) -int glue_objc_sync_exit(id _Nullable object)(a0) -id glue_objc_getProperty(id _Nonnull self, SEL _Nonnull _cmd, ptrdiff_t offset, bool atomic)(a0,a1,d0,d1) -void glue_objc_setProperty(id _Nonnull self, SEL _Nonnull _cmd, ptrdiff_t offset, id value, bool atomic, signed char copy)(a0,a1,d0,a2,d1,d2) -void glue_objc_getPropertyStruct(void *_Nonnull dest, const void *_Nonnull src, ptrdiff_t size, bool atomic, bool strong)(a0,a1,d0,d1,d2) -void glue_objc_setPropertyStruct(void *_Nonnull dest, const void *_Nonnull src, ptrdiff_t size, bool atomic, bool strong)(a0,a1,d0,d1,d2) -void glue_objc_enumerationMutation(id _Nonnull object)(a0) -int glue___gnu_objc_personality(int version, int actions, uint64_t *_Nonnull exClass, void *_Nonnull ex, void *_Nonnull ctx)(d0,d1,d2,a0,a1) -id _Nullable glue_objc_retain(id _Nullable object)(a0) -id _Nullable glue_objc_retainBlock(id _Nullable block)(a0) -id _Nullable glue_objc_retainAutorelease(id _Nullable object)(a0) -void glue_objc_release(id _Nullable object)(a0) -id _Nullable glue_objc_autorelease(id _Nullable object)(a0) -id _Nullable glue_objc_autoreleaseReturnValue(id _Nullable object)(a0) -id _Nullable glue_objc_retainAutoreleaseReturnValue(id _Nullable object)(a0) -id _Nullable glue_objc_retainAutoreleasedReturnValue(id _Nullable object)(a0) -id _Nullable glue_objc_storeStrong(id _Nullable *_Nonnull object, id _Nullable value)(a0,a1) -id _Nullable glue_objc_storeWeak(id _Nullable *_Nonnull object, id _Nullable value)(a0,a1) -id _Nullable glue_objc_loadWeakRetained(id _Nullable *_Nonnull object)(a0) -id _Nullable glue_objc_initWeak(id _Nullable *_Nonnull object, id _Nullable value)(a0,a1) -void glue_objc_destroyWeak(id _Nullable *_Nonnull object)(a0) -id _Nullable glue_objc_loadWeak(id _Nullable *_Nonnull object)(a0) -void glue_objc_copyWeak(id _Nullable *_Nonnull dest, id _Nullable *_Nonnull src)(a0,a1) -void glue_objc_moveWeak(id _Nullable *_Nonnull dest, id _Nullable *_Nonnull src)(a0,a1) -SEL _Nonnull glue_sel_registerName(const char *_Nonnull name)(a0) -const char *_Nonnull glue_sel_getName(SEL _Nonnull selector)(a0) -bool glue_sel_isEqual(SEL _Nonnull selector1, SEL _Nonnull selector2)(a0,a1) -Class _Nonnull glue_objc_allocateClassPair(Class _Nullable superclass, const char *_Nonnull name, size_t extraBytes)(a0,a1,d0) -void glue_objc_registerClassPair(Class _Nonnull class_)(a0) -unsigned int glue_objc_getClassList(Class _Nonnull *_Nullable buffer, unsigned int count)(a0,d0) -Class _Nonnull *_Nonnull glue_objc_copyClassList(unsigned int *_Nullable length)(a0) -bool glue_class_isMetaClass(Class _Nullable class_)(a0) -const char *_Nullable glue_class_getName(Class _Nullable class_)(a0) -Class _Nullable glue_class_getSuperclass(Class _Nullable class_)(a0) -unsigned long glue_class_getInstanceSize(Class _Nullable class_)(a0) -bool glue_class_respondsToSelector(Class _Nullable class_, SEL _Nonnull selector)(a0,a1) -bool glue_class_conformsToProtocol(Class _Nullable class_, Protocol *_Nonnull p)(a0,a1) -IMP _Nullable glue_class_getMethodImplementation(Class _Nullable class_, SEL _Nonnull selector)(a0,a1) -IMP _Nullable glue_class_getMethodImplementation_stret(Class _Nullable class_, SEL _Nonnull selector)(a0,a1) -Method _Nullable glue_class_getInstanceMethod(Class _Nullable class_, SEL _Nonnull selector)(a0,a1) -bool glue_class_addMethod(Class _Nonnull class_, SEL _Nonnull selector, IMP _Nonnull implementation, const char *_Nullable typeEncoding)(a0,a1,a2,a3) -IMP _Nullable glue_class_replaceMethod(Class _Nonnull class_, SEL _Nonnull selector, IMP _Nonnull implementation, const char *_Nullable typeEncoding)(a0,a1,a2,a3) -Class _Nullable glue_object_getClass(id _Nullable object)(a0) -Class _Nullable glue_object_setClass(id _Nullable object, Class _Nonnull class_)(a0,a1) -const char *_Nullable glue_object_getClassName(id _Nullable object)(a0) -const char *_Nonnull glue_protocol_getName(Protocol *_Nonnull protocol)(a0) -bool glue_protocol_isEqual(Protocol *_Nonnull protocol1, Protocol *_Nonnull protocol2)(a0,a1) -bool glue_protocol_conformsToProtocol(Protocol *_Nonnull protocol1, Protocol *_Nonnull protocol2)(a0,a1) -_Nullable objc_uncaught_exception_handler_t glue_objc_setUncaughtExceptionHandler(objc_uncaught_exception_handler_t _Nullable handler)(a0) -void glue_objc_setForwardHandler(IMP _Nullable forward, IMP _Nullable stretForward)(a0,a1) -void glue_objc_setEnumerationMutationHandler(objc_enumeration_mutation_handler_t _Nullable handler)(a0) -id _Nullable glue_objc_constructInstance(Class _Nullable class_, void *_Nullable bytes)(a0,a1) -void glue_objc_exit(void)() -Ivar _Nullable *_Nullable glue_class_copyIvarList(Class _Nullable class_, unsigned int *_Nullable outCount)(a0,a1) -const char *_Nonnull glue_ivar_getName(Ivar _Nonnull ivar)(a0) -const char *_Nonnull glue_ivar_getTypeEncoding(Ivar _Nonnull ivar)(a0) -ptrdiff_t glue_ivar_getOffset(Ivar _Nonnull ivar)(a0) -Method _Nullable *_Nullable glue_class_copyMethodList(Class _Nullable class_, unsigned int *_Nullable outCount)(a0,a1) -SEL _Nonnull glue_method_getName(Method _Nonnull method)(a0) -const char *_Nullable glue_method_getTypeEncoding(Method _Nonnull method)(a0) -objc_property_t _Nullable *_Nullable glue_class_copyPropertyList(Class _Nullable class_, unsigned int *_Nullable outCount)(a0,a1) -const char *_Nonnull glue_property_getName(objc_property_t _Nonnull property)(a0) -char *_Nullable glue_property_copyAttributeValue(objc_property_t _Nonnull property, const char *_Nonnull name)(a0,a1) -void *_Nullable glue_objc_destructInstance(id _Nullable object)(a0) -void *_Null_unspecified glue_objc_autoreleasePoolPush(void)() -void glue_objc_autoreleasePoolPop(void *_Null_unspecified pool)(a0) -id _Nullable glue__objc_rootAutorelease(id _Nullable object)(a0) -* The following functions are private! Don't use! -struct objc_hashtable *_Nonnull glue_objc_hashtable_new(objc_hashtable_hash_func hash, objc_hashtable_equal_func equal, uint32_t size)(a0,a1,d0) -void glue_objc_hashtable_set(struct objc_hashtable *_Nonnull table, const void *_Nonnull key, const void *_Nonnull object)(a0,a1,a2) -void *_Nullable glue_objc_hashtable_get(struct objc_hashtable *_Nonnull table, const void *_Nonnull key)(a0,a1) -void glue_objc_hashtable_delete(struct objc_hashtable *_Nonnull table, const void *_Nonnull key)(a0,a1) -void glue_objc_hashtable_free(struct objc_hashtable *_Nonnull table)(a0) -* Public functions again -void glue_objc_setTaggedPointerSecret(uintptr_t secret)(d0) -int glue_objc_registerTaggedPointerClass(Class _Nonnull class_)(a0) -bool glue_object_isTaggedPointer(id _Nullable object)(a0) -uintptr_t glue_object_getTaggedPointerValue(id _Nonnull object)(a0) -id _Nullable glue_objc_createTaggedPointer(int class_, uintptr_t value)(d0,d1) -==end Index: src/runtime/arc.m ================================================================== --- src/runtime/arc.m +++ src/runtime/arc.m @@ -20,11 +20,11 @@ #ifdef OF_HAVE_THREADS # import "OFPlainMutex.h" #endif -struct weakref { +struct WeakRef { id **locations; size_t count; }; static struct objc_hashtable *hashtable; @@ -115,11 +115,11 @@ } id objc_storeWeak(id *object, id value) { - struct weakref *old; + struct WeakRef *old; #ifdef OF_HAVE_THREADS if (OFSpinlockLock(&spinlock) != 0) OBJC_ERROR("Failed to lock spinlock!"); #endif @@ -153,11 +153,11 @@ } } if (value != nil && class_respondsToSelector(object_getClass(value), @selector(allowsWeakReference)) && [value allowsWeakReference]) { - struct weakref *ref = objc_hashtable_get(hashtable, value); + struct WeakRef *ref = objc_hashtable_get(hashtable, value); if (ref == NULL) { if ((ref = calloc(1, sizeof(*ref))) == NULL) OBJC_ERROR("Not enough memory to allocate weak " "reference!"); @@ -186,11 +186,11 @@ id objc_loadWeakRetained(id *object) { id value = nil; - struct weakref *ref; + struct WeakRef *ref; #ifdef OF_HAVE_THREADS if (OFSpinlockLock(&spinlock) != 0) OBJC_ERROR("Failed to lock spinlock!"); #endif @@ -237,11 +237,11 @@ } void objc_moveWeak(id *dest, id *src) { - struct weakref *ref; + struct WeakRef *ref; #ifdef OF_HAVE_THREADS if (OFSpinlockLock(&spinlock) != 0) OBJC_ERROR("Failed to lock spinlock!"); #endif @@ -264,13 +264,13 @@ OBJC_ERROR("Failed to unlock spinlock!"); #endif } void -objc_zero_weak_references(id value) +objc_zeroWeakReferences(id value) { - struct weakref *ref; + struct WeakRef *ref; #ifdef OF_HAVE_THREADS if (OFSpinlockLock(&spinlock) != 0) OBJC_ERROR("Failed to lock spinlock!"); #endif Index: src/runtime/autorelease.m ================================================================== --- src/runtime/autorelease.m +++ src/runtime/autorelease.m @@ -33,10 +33,15 @@ #ifndef OF_OBJFW_RUNTIME @interface DummyObject - (void)release; @end #endif + +#ifndef OBJC_ERROR +/* This is also used with old Apple runtimes that lack autorelease pools. */ +# define OBJC_ERROR(...) abort() +#endif #if defined(OF_HAVE_COMPILER_TLS) static thread_local id *objects = NULL; static thread_local uintptr_t count = 0; static thread_local uintptr_t size = 0; @@ -49,13 +54,13 @@ #endif #if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) OF_CONSTRUCTOR() { - OFEnsure(OFTLSKeyNew(&objectsKey) == 0); - OFEnsure(OFTLSKeyNew(&countKey) == 0); - OFEnsure(OFTLSKeyNew(&sizeKey) == 0); + if (OFTLSKeyNew(&objectsKey) != 0 || OFTLSKeyNew(&countKey) != 0 || + OFTLSKeyNew(&sizeKey) != 0) + OBJC_ERROR("Failed to create TLS keys!"); } #endif void * objc_autoreleasePoolPush() @@ -96,17 +101,19 @@ free(objects); objects = NULL; #if defined(OF_HAVE_COMPILER_TLS) || !defined(OF_HAVE_THREADS) size = 0; #else - OFEnsure(OFTLSKeySet(objectsKey, objects) == 0); - OFEnsure(OFTLSKeySet(sizeKey, (void *)0) == 0); + if (OFTLSKeySet(objectsKey, objects) != 0 || + OFTLSKeySet(sizeKey, (void *)0) != 0) + OBJC_ERROR("Failed to set TLS key!"); #endif } #if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) - OFEnsure(OFTLSKeySet(countKey, (void *)count) == 0); + if (OFTLSKeySet(countKey, (void *)count) != 0) + OBJC_ERROR("Failed to set TLS key!"); #endif } id _objc_rootAutorelease(id object) @@ -121,22 +128,24 @@ if (size == 0) size = 16; else size *= 2; - OFEnsure((objects = - realloc(objects, size * sizeof(id))) != NULL); + if ((objects = realloc(objects, size * sizeof(id))) == NULL) + OBJC_ERROR("Failed to resize autorelease pool!"); #if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) - OFEnsure(OFTLSKeySet(objectsKey, objects) == 0); - OFEnsure(OFTLSKeySet(sizeKey, (void *)size) == 0); + if (OFTLSKeySet(objectsKey, objects) != 0 || + OFTLSKeySet(sizeKey, (void *)size) != 0) + OBJC_ERROR("Failed to set TLS key!"); #endif } objects[count++] = object; #if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) - OFEnsure(OFTLSKeySet(countKey, (void *)count) == 0); + if (OFTLSKeySet(countKey, (void *)count) != 0) + OBJC_ERROR("Failed to set TLS key!"); #endif return object; } Index: src/runtime/category.m ================================================================== --- src/runtime/category.m +++ src/runtime/category.m @@ -30,26 +30,26 @@ struct objc_method_list *iter; unsigned int i; for (iter = category->instanceMethods; iter != NULL; iter = iter->next) for (i = 0; i < iter->count; i++) - objc_register_selector(&iter->methods[i].selector); + objc_registerSelector(&iter->methods[i].selector); for (iter = category->classMethods; iter != NULL; iter = iter->next) for (i = 0; i < iter->count; i++) - objc_register_selector(&iter->methods[i].selector); + objc_registerSelector(&iter->methods[i].selector); } static void registerCategory(struct objc_category *category) { struct objc_category **categories; - Class class = objc_classname_to_class(category->className, false); + Class class = objc_classnameToClass(category->className, false); if (categoriesMap == NULL) categoriesMap = objc_hashtable_new( - objc_hash_string, objc_equal_string, 2); + objc_string_hash, objc_string_equal, 2); categories = (struct objc_category **)objc_hashtable_get( categoriesMap, category->className); if (categories != NULL) { @@ -68,12 +68,12 @@ newCategories[i + 1] = NULL; objc_hashtable_set(categoriesMap, category->className, newCategories); if (class != Nil && class->info & OBJC_CLASS_INFO_SETUP) { - objc_update_dtable(class); - objc_update_dtable(class->isa); + objc_updateDTable(class); + objc_updateDTable(class->isa); } return; } @@ -84,17 +84,17 @@ categories[0] = category; categories[1] = NULL; objc_hashtable_set(categoriesMap, category->className, categories); if (class != Nil && class->info & OBJC_CLASS_INFO_SETUP) { - objc_update_dtable(class); - objc_update_dtable(class->isa); + objc_updateDTable(class); + objc_updateDTable(class->isa); } } void -objc_register_all_categories(struct objc_symtab *symtab) +objc_registerAllCategories(struct objc_symtab *symtab) { struct objc_category **categories = (struct objc_category **)symtab->defs + symtab->classDefsCount; for (size_t i = 0; i < symtab->categoryDefsCount; i++) { @@ -102,21 +102,21 @@ registerCategory(categories[i]); } } struct objc_category ** -objc_categories_for_class(Class class) +objc_categoriesForClass(Class class) { if (categoriesMap == NULL) return NULL; return (struct objc_category **)objc_hashtable_get(categoriesMap, class->name); } void -objc_unregister_all_categories(void) +objc_unregisterAllCategories(void) { if (categoriesMap == NULL) return; for (uint32_t i = 0; i < categoriesMap->size; i++) Index: src/runtime/class.m ================================================================== --- src/runtime/class.m +++ src/runtime/class.m @@ -34,38 +34,38 @@ static void registerClass(Class class) { if (classes == NULL) classes = objc_hashtable_new( - objc_hash_string, objc_equal_string, 2); + objc_string_hash, objc_string_equal, 2); objc_hashtable_set(classes, class->name, class); if (emptyDTable == NULL) emptyDTable = objc_dtable_new(); - class->DTable = emptyDTable; - class->isa->DTable = emptyDTable; + class->dTable = emptyDTable; + class->isa->dTable = emptyDTable; if (strcmp(class->name, "Protocol") != 0) classesCount++; } bool class_registerAlias_np(Class class, const char *name) { - objc_global_mutex_lock(); + objc_globalMutex_lock(); if (classes == NULL) { - objc_global_mutex_unlock(); + objc_globalMutex_unlock(); return NO; } objc_hashtable_set(classes, name, (Class)((uintptr_t)class | 1)); - objc_global_mutex_unlock(); + objc_globalMutex_unlock(); return YES; } static void @@ -74,15 +74,15 @@ struct objc_method_list *iter; unsigned int i; for (iter = class->methodList; iter != NULL; iter = iter->next) for (i = 0; i < iter->count; i++) - objc_register_selector(&iter->methods[i].selector); + objc_registerSelector(&iter->methods[i].selector); } Class -objc_classname_to_class(const char *name, bool cache) +objc_classnameToClass(const char *name, bool cache) { Class class; if (classes == NULL) return Nil; @@ -113,21 +113,21 @@ if (class != Nil) return class; } - objc_global_mutex_lock(); + objc_globalMutex_lock(); class = (Class)((uintptr_t)objc_hashtable_get(classes, name) & ~1); if (cache && fastPath == NULL && --lookupsUntilFastPath == 0) fastPath = objc_sparsearray_new(sizeof(uintptr_t)); if (cache && fastPath != NULL) objc_sparsearray_set(fastPath, (uintptr_t)name, class); - objc_global_mutex_unlock(); + objc_globalMutex_unlock(); return class; } static void @@ -178,31 +178,31 @@ class->info |= OBJC_CLASS_INFO_LOADED; } void -objc_update_dtable(Class class) +objc_updateDTable(Class class) { struct objc_category **categories; if (!(class->info & OBJC_CLASS_INFO_DTABLE)) return; - if (class->DTable == emptyDTable) - class->DTable = objc_dtable_new(); + if (class->dTable == emptyDTable) + class->dTable = objc_dtable_new(); if (class->superclass != Nil) - objc_dtable_copy(class->DTable, class->superclass->DTable); + objc_dtable_copy(class->dTable, class->superclass->dTable); for (struct objc_method_list *methodList = class->methodList; methodList != NULL; methodList = methodList->next) for (unsigned int i = 0; i < methodList->count; i++) - objc_dtable_set(class->DTable, + objc_dtable_set(class->dTable, (uint32_t)methodList->methods[i].selector.UID, methodList->methods[i].implementation); - if ((categories = objc_categories_for_class(class)) != NULL) { + if ((categories = objc_categoriesForClass(class)) != NULL) { for (unsigned int i = 0; categories[i] != NULL; i++) { struct objc_method_list *methodList = (class->info & OBJC_CLASS_INFO_CLASS ? categories[i]->instanceMethods : categories[i]->classMethods); @@ -209,21 +209,21 @@ for (; methodList != NULL; methodList = methodList->next) for (unsigned int j = 0; j < methodList->count; j++) - objc_dtable_set(class->DTable, + objc_dtable_set(class->dTable, (uint32_t)methodList->methods[j] .selector.UID, methodList->methods[j] .implementation); } } if (class->subclassList != NULL) for (Class *iter = class->subclassList; *iter != NULL; iter++) - objc_update_dtable(*iter); + objc_updateDTable(*iter); } static void addSubclass(Class class) { @@ -280,26 +280,26 @@ for (unsigned int i = 0; i < class->ivars->count; i++) *class->ivarOffsets[i] = class->ivars->ivars[i].offset; } static void -setupClass(Class class) +setUpClass(Class class) { const char *superclassName; if (class->info & OBJC_CLASS_INFO_SETUP) return; superclassName = (const char *)class->superclass; if (superclassName != NULL) { - Class super = objc_classname_to_class(superclassName, false); + Class super = objc_classnameToClass(superclassName, false); Class rootClass; if (super == Nil) return; - setupClass(super); + setUpClass(super); if (!(super->info & OBJC_CLASS_INFO_SETUP)) return; /* @@ -349,12 +349,12 @@ return; class->info |= OBJC_CLASS_INFO_DTABLE; class->isa->info |= OBJC_CLASS_INFO_DTABLE; - objc_update_dtable(class); - objc_update_dtable(class->isa); + objc_updateDTable(class); + objc_updateDTable(class->isa); /* * Set it first to prevent calling it recursively due to message sends * in the initialize method */ @@ -373,44 +373,44 @@ initialize(class, initializeSel); } } void -objc_initialize_class(Class class) +objc_initializeClass(Class class) { if (class->info & OBJC_CLASS_INFO_INITIALIZED) return; - objc_global_mutex_lock(); + objc_globalMutex_lock(); /* * It's possible that two threads try to initialize a class at the same * time. Make sure that the thread which held the lock did not already * initialize it. */ if (class->info & OBJC_CLASS_INFO_INITIALIZED) { - objc_global_mutex_unlock(); + objc_globalMutex_unlock(); return; } - setupClass(class); + setUpClass(class); if (!(class->info & OBJC_CLASS_INFO_SETUP)) { - objc_global_mutex_unlock(); + objc_globalMutex_unlock(); return; } initializeClass(class); - objc_global_mutex_unlock(); + objc_globalMutex_unlock(); } static void processLoadQueue() { for (size_t i = 0; i < loadQueueCount; i++) { - setupClass(loadQueue[i]); + setUpClass(loadQueue[i]); if (loadQueue[i]->info & OBJC_CLASS_INFO_SETUP) { callLoad(loadQueue[i]); loadQueueCount--; @@ -431,11 +431,11 @@ } } } void -objc_register_all_classes(struct objc_symtab *symtab) +objc_registerAllClasses(struct objc_symtab *symtab) { for (uint16_t i = 0; i < symtab->classDefsCount; i++) { Class class = (Class)symtab->defs[i]; registerClass(class); @@ -445,11 +445,11 @@ for (uint16_t i = 0; i < symtab->classDefsCount; i++) { Class class = (Class)symtab->defs[i]; if (hasLoad(class)) { - setupClass(class); + setUpClass(class); if (class->info & OBJC_CLASS_INFO_SETUP) callLoad(class); else { loadQueue = realloc(loadQueue, @@ -472,13 +472,10 @@ objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes) { struct objc_class *class, *metaclass; Class iter, rootclass = Nil; - if (extraBytes > LONG_MAX) - OBJC_ERROR("extraBytes out of range!"); - if ((class = calloc(1, sizeof(*class))) == NULL || (metaclass = calloc(1, sizeof(*class))) == NULL) OBJC_ERROR("Not enough memory to allocate class pair for class " "%s!", name); @@ -485,11 +482,17 @@ class->isa = metaclass; class->superclass = superclass; class->name = name; class->info = OBJC_CLASS_INFO_CLASS; class->instanceSize = (superclass != Nil ? - superclass->instanceSize : 0) + (long)extraBytes; + superclass->instanceSize : 0); + + if (extraBytes > LONG_MAX || + LONG_MAX - class->instanceSize < (long)extraBytes) + OBJC_ERROR("extraBytes too large!"); + + class->instanceSize += (long)extraBytes; for (iter = superclass; iter != Nil; iter = iter->superclass) rootclass = iter; metaclass->isa = (rootclass != Nil ? rootclass->isa : class); @@ -503,11 +506,11 @@ } void objc_registerClassPair(Class class) { - objc_global_mutex_lock(); + objc_globalMutex_lock(); registerClass(class); if (class->superclass != Nil) { addSubclass(class); @@ -522,29 +525,29 @@ else class->info |= OBJC_CLASS_INFO_LOADED; processLoadQueue(); - objc_global_mutex_unlock(); + objc_globalMutex_unlock(); } Class objc_lookUpClass(const char *name) { Class class; - if ((class = objc_classname_to_class(name, true)) == NULL) + if ((class = objc_classnameToClass(name, true)) == NULL) return Nil; if (class->info & OBJC_CLASS_INFO_SETUP) return class; - objc_global_mutex_lock(); + objc_globalMutex_lock(); - setupClass(class); + setUpClass(class); - objc_global_mutex_unlock(); + objc_globalMutex_unlock(); if (!(class->info & OBJC_CLASS_INFO_SETUP)) return Nil; return class; @@ -581,11 +584,11 @@ unsigned int objc_getClassList(Class *buffer, unsigned int count) { unsigned int j; - objc_global_mutex_lock(); + objc_globalMutex_lock(); if (buffer == NULL) return classesCount; if (classesCount < count) @@ -594,11 +597,11 @@ j = 0; for (uint32_t i = 0; i < classes->size; i++) { void *class; if (j >= count) { - objc_global_mutex_unlock(); + objc_globalMutex_unlock(); return j; } if (classes->data[i] == NULL) continue; @@ -612,11 +615,11 @@ continue; buffer[j++] = class; } - objc_global_mutex_unlock(); + objc_globalMutex_unlock(); return j; } Class * @@ -623,24 +626,25 @@ objc_copyClassList(unsigned int *length) { Class *ret; unsigned int count; - objc_global_mutex_lock(); + objc_globalMutex_lock(); if ((ret = malloc((classesCount + 1) * sizeof(Class))) == NULL) OBJC_ERROR("Failed to allocate memory for class list!"); count = objc_getClassList(ret, classesCount); - OFEnsure(count == classesCount); + if (count != classesCount) + OBJC_ERROR("Fatal internal inconsistency!"); ret[count] = Nil; if (length != NULL) *length = count; - objc_global_mutex_unlock(); + objc_globalMutex_unlock(); return ret; } bool @@ -724,11 +728,11 @@ static struct objc_method * getMethod(Class class, SEL selector) { struct objc_category **categories; - if ((categories = objc_categories_for_class(class)) != NULL) { + if ((categories = objc_categoriesForClass(class)) != NULL) { for (; *categories != NULL; categories++) { struct objc_method_list *methodList = (class->info & OBJC_CLASS_INFO_METACLASS ? (*categories)->classMethods : (*categories)->instanceMethods); @@ -758,11 +762,11 @@ addMethod(Class class, SEL selector, IMP implementation, const char *typeEncoding) { struct objc_method_list *methodList; - /* FIXME: We need a way to free this at objc_exit() */ + /* FIXME: We need a way to free this at objc_deinit() */ if ((methodList = malloc(sizeof(*methodList))) == NULL) OBJC_ERROR("Not enough memory to replace method!"); methodList->next = class->methodList; methodList->count = 1; @@ -770,11 +774,11 @@ methodList->methods[0].selector.typeEncoding = typeEncoding; methodList->methods[0].implementation = implementation; class->methodList = methodList; - objc_update_dtable(class); + objc_updateDTable(class); } Method class_getInstanceMethod(Class class, SEL selector) { @@ -782,20 +786,20 @@ Class superclass; if (class == Nil) return NULL; - objc_global_mutex_lock(); + objc_globalMutex_lock(); if ((method = getMethod(class, selector)) != NULL) { - objc_global_mutex_unlock(); + objc_globalMutex_unlock(); return method; } superclass = class->superclass; - objc_global_mutex_unlock(); + objc_globalMutex_unlock(); if (superclass != Nil) return class_getInstanceMethod(superclass, selector); return NULL; @@ -805,19 +809,19 @@ class_addMethod(Class class, SEL selector, IMP implementation, const char *typeEncoding) { bool ret; - objc_global_mutex_lock(); + objc_globalMutex_lock(); if (getMethod(class, selector) == NULL) { addMethod(class, selector, implementation, typeEncoding); ret = true; } else ret = false; - objc_global_mutex_unlock(); + objc_globalMutex_unlock(); return ret; } IMP @@ -825,22 +829,22 @@ const char *typeEncoding) { struct objc_method *method; IMP oldImplementation; - objc_global_mutex_lock(); + objc_globalMutex_lock(); if ((method = getMethod(class, selector)) != NULL) { oldImplementation = method->implementation; method->implementation = implementation; - objc_update_dtable(class); + objc_updateDTable(class); } else { oldImplementation = NULL; addMethod(class, selector, implementation, typeEncoding); } - objc_global_mutex_unlock(); + objc_globalMutex_unlock(); return oldImplementation; } Class @@ -912,31 +916,33 @@ if (class->subclassList != NULL) { free(class->subclassList); class->subclassList = NULL; } - if (class->DTable != NULL && class->DTable != emptyDTable) - objc_dtable_free(class->DTable); + if (class->dTable != NULL && class->dTable != emptyDTable) + objc_dtable_free(class->dTable); - class->DTable = NULL; + class->dTable = NULL; if ((class->info & OBJC_CLASS_INFO_SETUP) && class->superclass != Nil) class->superclass = (Class)class->superclass->name; class->info &= ~OBJC_CLASS_INFO_SETUP; } void -objc_unregister_class(Class class) +objc_unregisterClass(Class class) { static SEL unloadSel = NULL; + + objc_globalMutex_lock(); if (unloadSel == NULL) unloadSel = sel_registerName("unload"); while (class->subclassList != NULL && class->subclassList[0] != Nil) - objc_unregister_class(class->subclassList[0]); + objc_unregisterClass(class->subclassList[0]); if (class->info & OBJC_CLASS_INFO_LOADED) callSelector(class, unloadSel); objc_hashtable_delete(classes, class->name); @@ -944,27 +950,29 @@ if (strcmp(class_getName(class), "Protocol") != 0) classesCount--; unregisterClass(class); unregisterClass(class->isa); + + objc_globalMutex_unlock(); } void -objc_unregister_all_classes(void) +objc_unregisterAllClasses(void) { if (classes == NULL) return; for (uint32_t i = 0; i < classes->size; i++) { if (classes->data[i] != NULL && - classes->data[i] != &objc_deleted_bucket) { + classes->data[i] != &objc_deletedBucket) { void *class = (Class)classes->data[i]->object; if (class == Nil || (uintptr_t)class & 1) continue; - objc_unregister_class(class); + objc_unregisterClass(class); /* * The table might have been resized, so go back to the * start again. * @@ -974,11 +982,12 @@ */ i = UINT32_MAX; } } - OFEnsure(classesCount == 0); + if (classesCount != 0) + OBJC_ERROR("Fatal internal inconsistency!"); if (emptyDTable != NULL) { objc_dtable_free(emptyDTable); emptyDTable = NULL; } Index: src/runtime/dtable.m ================================================================== --- src/runtime/dtable.m +++ src/runtime/dtable.m @@ -28,15 +28,15 @@ static void init(void) { if ((emptyLevel2 = malloc(sizeof(*emptyLevel2))) == NULL) - OBJC_ERROR("Not enough memory to allocate dtable!"); + OBJC_ERROR("Not enough memory to allocate dispatch table!"); #ifdef OF_SELUID24 if ((emptyLevel3 = malloc(sizeof(*emptyLevel3))) == NULL) - OBJC_ERROR("Not enough memory to allocate dtable!"); + OBJC_ERROR("Not enough memory to allocate dispatch table!"); #endif #ifdef OF_SELUID24 for (uint_fast16_t i = 0; i < 256; i++) { emptyLevel2->buckets[i] = emptyLevel3; @@ -49,27 +49,27 @@ } struct objc_dtable * objc_dtable_new(void) { - struct objc_dtable *DTable; + struct objc_dtable *dTable; #ifdef OF_SELUID24 if (emptyLevel2 == NULL || emptyLevel3 == NULL) init(); #else if (emptyLevel2 == NULL) init(); #endif - if ((DTable = malloc(sizeof(*DTable))) == NULL) - OBJC_ERROR("Not enough memory to allocate dtable!"); + if ((dTable = malloc(sizeof(*dTable))) == NULL) + OBJC_ERROR("Not enough memory to allocate dispatch table!"); for (uint_fast16_t i = 0; i < 256; i++) - DTable->buckets[i] = emptyLevel2; + dTable->buckets[i] = emptyLevel2; - return DTable; + return dTable; } void objc_dtable_copy(struct objc_dtable *dest, struct objc_dtable *src) { @@ -111,11 +111,11 @@ #endif } } void -objc_dtable_set(struct objc_dtable *DTable, uint32_t idx, IMP implementation) +objc_dtable_set(struct objc_dtable *dTable, uint32_t idx, IMP implementation) { #ifdef OF_SELUID24 uint8_t i = idx >> 16; uint8_t j = idx >> 8; uint8_t k = idx; @@ -122,62 +122,64 @@ #else uint8_t i = idx >> 8; uint8_t j = idx; #endif - if (DTable->buckets[i] == emptyLevel2) { + if (dTable->buckets[i] == emptyLevel2) { struct objc_dtable_level2 *level2 = malloc(sizeof(*level2)); if (level2 == NULL) - OBJC_ERROR("Not enough memory to insert into dtable!"); + OBJC_ERROR("Not enough memory to insert into " + "dispatch table!"); for (uint_fast16_t l = 0; l < 256; l++) #ifdef OF_SELUID24 level2->buckets[l] = emptyLevel3; #else level2->buckets[l] = (IMP)0; #endif - DTable->buckets[i] = level2; + dTable->buckets[i] = level2; } #ifdef OF_SELUID24 - if (DTable->buckets[i]->buckets[j] == emptyLevel3) { + if (dTable->buckets[i]->buckets[j] == emptyLevel3) { struct objc_dtable_level3 *level3 = malloc(sizeof(*level3)); if (level3 == NULL) - OBJC_ERROR("Not enough memory to insert into dtable!"); + OBJC_ERROR("Not enough memory to insert into " + "dispatch table!"); for (uint_fast16_t l = 0; l < 256; l++) level3->buckets[l] = (IMP)0; - DTable->buckets[i]->buckets[j] = level3; + dTable->buckets[i]->buckets[j] = level3; } - DTable->buckets[i]->buckets[j]->buckets[k] = implementation; + dTable->buckets[i]->buckets[j]->buckets[k] = implementation; #else - DTable->buckets[i]->buckets[j] = implementation; + dTable->buckets[i]->buckets[j] = implementation; #endif } void -objc_dtable_free(struct objc_dtable *DTable) +objc_dtable_free(struct objc_dtable *dTable) { for (uint_fast16_t i = 0; i < 256; i++) { - if (DTable->buckets[i] == emptyLevel2) + if (dTable->buckets[i] == emptyLevel2) continue; #ifdef OF_SELUID24 for (uint_fast16_t j = 0; j < 256; j++) - if (DTable->buckets[i]->buckets[j] != emptyLevel3) - free(DTable->buckets[i]->buckets[j]); + if (dTable->buckets[i]->buckets[j] != emptyLevel3) + free(dTable->buckets[i]->buckets[j]); #endif - free(DTable->buckets[i]); + free(dTable->buckets[i]); } - free(DTable); + free(dTable); } void objc_dtable_cleanup(void) { Index: src/runtime/exception.m ================================================================== --- src/runtime/exception.m +++ src/runtime/exception.m @@ -67,42 +67,48 @@ #define GNUCOBJC_EXCEPTION_CLASS UINT64_C(0x474E55434F424A43) /* GNUCOBJC */ #define GNUCCXX0_EXCEPTION_CLASS UINT64_C(0x474E5543432B2B00) /* GNUCC++\0 */ #define CLNGCXX0_EXCEPTION_CLASS UINT64_C(0x434C4E47432B2B00) /* CLNGC++\0 */ -#define NUM_EMERGENCY_EXCEPTIONS 4 - -#define _UA_SEARCH_PHASE 0x01 -#define _UA_CLEANUP_PHASE 0x02 -#define _UA_HANDLER_FRAME 0x04 -#define _UA_FORCE_UNWIND 0x08 - -#define DW_EH_PE_absptr 0x00 - -#define DW_EH_PE_uleb128 0x01 -#define DW_EH_PE_udata2 0x02 -#define DW_EH_PE_udata4 0x03 -#define DW_EH_PE_udata8 0x04 - -#define DW_EH_PE_signed 0x08 -#define DW_EH_PE_sleb128 (DW_EH_PE_signed | DW_EH_PE_uleb128) -#define DW_EH_PE_sdata2 (DW_EH_PE_signed | DW_EH_PE_udata2) -#define DW_EH_PE_sdata4 (DW_EH_PE_signed | DW_EH_PE_udata4) -#define DW_EH_PE_sdata8 (DW_EH_PE_signed | DW_EH_PE_udata8) - -#define DW_EH_PE_pcrel 0x10 -#define DW_EH_PE_textrel 0x20 -#define DW_EH_PE_datarel 0x30 -#define DW_EH_PE_funcrel 0x40 -#define DW_EH_PE_aligned 0x50 - -#define DW_EH_PE_indirect 0x80 - -#define DW_EH_PE_omit 0xFF - -#define CLEANUP_FOUND 0x01 -#define HANDLER_FOUND 0x02 +#define numEmergencyExceptions 4 + +enum { + _UA_SEARCH_PHASE = 0x01, + _UA_CLEANUP_PHASE = 0x02, + _UA_HANDLER_FRAME = 0x04, + _UA_FORCE_UNWIND = 0x08 +}; + +enum { + DW_EH_PE_absptr = 0x00, + + DW_EH_PE_uleb128 = 0x01, + DW_EH_PE_udata2 = 0x02, + DW_EH_PE_udata4 = 0x03, + DW_EH_PE_udata8 = 0x04, + + DW_EH_PE_signed = 0x08, + DW_EH_PE_sleb128 = (DW_EH_PE_signed | DW_EH_PE_uleb128), + DW_EH_PE_sdata2 = (DW_EH_PE_signed | DW_EH_PE_udata2), + DW_EH_PE_sdata4 = (DW_EH_PE_signed | DW_EH_PE_udata4), + DW_EH_PE_sdata8 = (DW_EH_PE_signed | DW_EH_PE_udata8), + + DW_EH_PE_pcrel = 0x10, + DW_EH_PE_textrel = 0x20, + DW_EH_PE_datarel = 0x30, + DW_EH_PE_funcrel = 0x40, + DW_EH_PE_aligned = 0x50, + + DW_EH_PE_indirect = 0x80, + + DW_EH_PE_omit = 0xFF +}; + +enum { + CLEANUP_FOUND = 0x01, + HANDLER_FOUND = 0x02 +}; struct _Unwind_Context; typedef enum { _URC_OK = 0, @@ -156,11 +162,11 @@ uintptr_t landingpad; intptr_t filter; #endif }; -struct lsda { +struct LSDA { uintptr_t regionStart, landingpadsStart; uint8_t typesTableEnc; const uint8_t *typesTable; uintptr_t typesTableBase; uint8_t callsitesEnc; @@ -237,19 +243,19 @@ extern EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD, void *, PCONTEXT, PDISPATCHER_CONTEXT, _Unwind_Reason_Code (*)(int, int, uint64_t, struct _Unwind_Exception *, struct _Unwind_Context *)); #endif -static objc_uncaught_exception_handler_t uncaughtExceptionHandler; -static struct objc_exception emergencyExceptions[NUM_EMERGENCY_EXCEPTIONS]; +static objc_uncaught_exception_handler uncaughtExceptionHandler; +static struct objc_exception emergencyExceptions[numEmergencyExceptions]; #ifdef OF_HAVE_THREADS static OFSpinlock emergencyExceptionsSpinlock; OF_CONSTRUCTOR() { if (OFSpinlockNew(&emergencyExceptionsSpinlock) != 0) - OBJC_ERROR("Cannot create spinlock!"); + OBJC_ERROR("Failed to create spinlock!"); } #endif static uint64_t readULEB128(const uint8_t **ptr) @@ -397,11 +403,11 @@ return value; } #endif static void -readLSDA(struct _Unwind_Context *ctx, const uint8_t *ptr, struct lsda *LSDA) +readLSDA(struct _Unwind_Context *ctx, const uint8_t *ptr, struct LSDA *LSDA) { uint8_t landingpadsStartEnc; uintptr_t callsitesSize; LSDA->regionStart = _Unwind_GetRegionStart(ctx); @@ -425,11 +431,11 @@ LSDA->actionTable = LSDA->callsites + callsitesSize; } static bool -findCallsite(struct _Unwind_Context *ctx, struct lsda *LSDA, +findCallsite(struct _Unwind_Context *ctx, struct LSDA *LSDA, uintptr_t *landingpad, const uint8_t **actionRecords) { uintptr_t IP = _Unwind_GetIP(ctx); const uint8_t *ptr = LSDA->callsites; @@ -502,11 +508,11 @@ return false; } static uint8_t -findActionRecord(const uint8_t *actionRecords, struct lsda *LSDA, int actions, +findActionRecord(const uint8_t *actionRecords, struct LSDA *LSDA, int actions, bool foreign, struct objc_exception *e, intptr_t *filterPtr) { const uint8_t *ptr; intptr_t filter, displacement; @@ -598,11 +604,11 @@ _Unwind_SetGR(ctx, 12, (uintptr_t)ex); #endif struct objc_exception *e = (struct objc_exception *)ex; bool foreign = (exClass != GNUCOBJC_EXCEPTION_CLASS); const uint8_t *LSDAAddr, *actionRecords; - struct lsda LSDA; + struct LSDA LSDA; uintptr_t landingpad = 0; uint8_t found = 0; intptr_t filter = 0; if (foreign) { @@ -710,18 +716,18 @@ emergencyExceptionCleanup(_Unwind_Reason_Code reason, struct _Unwind_Exception *ex) { #ifdef OF_HAVE_THREADS if (OFSpinlockLock(&emergencyExceptionsSpinlock) != 0) - OBJC_ERROR("Cannot lock spinlock!"); + OBJC_ERROR("Failed to lock spinlock!"); #endif ex->class = 0; #ifdef OF_HAVE_THREADS if (OFSpinlockUnlock(&emergencyExceptionsSpinlock) != 0) - OBJC_ERROR("Cannot unlock spinlock!"); + OBJC_ERROR("Failed to unlock spinlock!"); #endif } void objc_exception_throw(id object) @@ -730,14 +736,14 @@ bool emergency = false; if (e == NULL) { #ifdef OF_HAVE_THREADS if (OFSpinlockLock(&emergencyExceptionsSpinlock) != 0) - OBJC_ERROR("Cannot lock spinlock!"); + OBJC_ERROR("Failed to lock spinlock!"); #endif - for (uint_fast8_t i = 0; i < NUM_EMERGENCY_EXCEPTIONS; i++) { + for (uint_fast8_t i = 0; i < numEmergencyExceptions; i++) { if (emergencyExceptions[i].exception.class == 0) { e = &emergencyExceptions[i]; e->exception.class = GNUCOBJC_EXCEPTION_CLASS; emergency = true; @@ -745,11 +751,11 @@ } } #ifdef OF_HAVE_THREADS if (OFSpinlockUnlock(&emergencyExceptionsSpinlock) != 0) - OBJC_ERROR("Cannot lock spinlock!"); + OBJC_ERROR("Failed to lock spinlock!"); #endif } if (e == NULL) OBJC_ERROR("Not enough memory to allocate exception!"); @@ -765,14 +771,14 @@ uncaughtExceptionHandler(object); OBJC_ERROR("_Unwind_RaiseException() returned!"); } -objc_uncaught_exception_handler_t -objc_setUncaughtExceptionHandler(objc_uncaught_exception_handler_t handler) +objc_uncaught_exception_handler +objc_setUncaughtExceptionHandler(objc_uncaught_exception_handler handler) { - objc_uncaught_exception_handler_t old = uncaughtExceptionHandler; + objc_uncaught_exception_handler old = uncaughtExceptionHandler; uncaughtExceptionHandler = handler; return old; } Index: src/runtime/hashtable.m ================================================================== --- src/runtime/hashtable.m +++ src/runtime/hashtable.m @@ -22,14 +22,14 @@ #include #import "ObjFWRT.h" #import "private.h" -struct objc_hashtable_bucket objc_deleted_bucket; +struct objc_hashtable_bucket objc_deletedBucket; uint32_t -objc_hash_string(const void *str_) +objc_string_hash(const void *str_) { const char *str = str_; uint32_t hash = 0; while (*str != 0) { @@ -45,11 +45,11 @@ return hash; } bool -objc_equal_string(const void *ptr1, const void *ptr2) +objc_string_equal(const void *ptr1, const void *ptr2) { return (strcmp(ptr1, ptr2) == 0); } struct objc_hashtable * @@ -101,11 +101,11 @@ if ((newData = calloc(newSize, sizeof(*newData))) == NULL) OBJC_ERROR("Not enough memory to resize hash table!"); for (uint32_t i = 0; i < table->size; i++) { if (table->data[i] != NULL && - table->data[i] != &objc_deleted_bucket) { + table->data[i] != &objc_deletedBucket) { uint32_t j, last; last = newSize; for (j = table->data[i]->hash & (newSize - 1); @@ -117,11 +117,11 @@ for (j = 0; j < last && newData[j] != NULL; j++); } if (j >= last) - OBJC_ERROR("No free bucket!"); + OBJC_ERROR("No free bucket in hash table!"); newData[j] = table->data[i]; } } @@ -136,11 +136,11 @@ uint32_t i, hash; hash = table->hash(key) & (table->size - 1); for (i = hash; i < table->size && table->data[i] != NULL; i++) { - if (table->data[i] == &objc_deleted_bucket) + if (table->data[i] == &objc_deletedBucket) continue; if (table->equal(table->data[i]->key, key)) { *idx = i; return true; @@ -149,11 +149,11 @@ if (i < table->size) return false; for (i = 0; i < hash && table->data[i] != NULL; i++) { - if (table->data[i] == &objc_deleted_bucket) + if (table->data[i] == &objc_deletedBucket) continue; if (table->equal(table->data[i]->key, key)) { *idx = i; return true; @@ -179,21 +179,21 @@ hash = table->hash(key); last = table->size; for (i = hash & (table->size - 1); i < last && table->data[i] != NULL && - table->data[i] != &objc_deleted_bucket; i++); + table->data[i] != &objc_deletedBucket; i++); if (i >= last) { last = hash & (table->size - 1); for (i = 0; i < last && table->data[i] != NULL && - table->data[i] != &objc_deleted_bucket; i++); + table->data[i] != &objc_deletedBucket; i++); } if (i >= last) - OBJC_ERROR("No free bucket!"); + OBJC_ERROR("No free bucket in hash table!"); if ((bucket = malloc(sizeof(*bucket))) == NULL) OBJC_ERROR("Not enough memory to allocate hash table bucket!"); bucket->key = key; @@ -222,11 +222,11 @@ if (!indexForKey(table, key, &idx)) return; free(table->data[idx]); - table->data[idx] = &objc_deleted_bucket; + table->data[idx] = &objc_deletedBucket; table->count--; resize(table, table->count); } @@ -233,11 +233,11 @@ void objc_hashtable_free(struct objc_hashtable *table) { for (uint32_t i = 0; i < table->size; i++) if (table->data[i] != NULL && - table->data[i] != &objc_deleted_bucket) + table->data[i] != &objc_deletedBucket) free(table->data[i]); free(table->data); free(table); } Index: src/runtime/init.m ================================================================== --- src/runtime/init.m +++ src/runtime/init.m @@ -19,28 +19,28 @@ #import "private.h" void __objc_exec_class(struct objc_module *module) { - objc_global_mutex_lock(); - - objc_register_all_selectors(module->symtab); - objc_register_all_classes(module->symtab); - objc_register_all_categories(module->symtab); - objc_init_static_instances(module->symtab); - - objc_global_mutex_unlock(); + objc_globalMutex_lock(); + + objc_registerAllSelectors(module->symtab); + objc_registerAllClasses(module->symtab); + objc_registerAllCategories(module->symtab); + objc_initStaticInstances(module->symtab); + + objc_globalMutex_unlock(); } void -objc_exit(void) -{ - objc_global_mutex_lock(); - - objc_unregister_all_categories(); - objc_unregister_all_classes(); - objc_unregister_all_selectors(); - objc_forget_pending_static_instances(); +objc_deinit(void) +{ + objc_globalMutex_lock(); + + objc_unregisterAllCategories(); + objc_unregisterAllClasses(); + objc_unregisterAllSelectors(); + objc_forgetPendingStaticInstances(); objc_dtable_cleanup(); - objc_global_mutex_unlock(); + objc_globalMutex_unlock(); } Index: src/runtime/instance.m ================================================================== --- src/runtime/instance.m +++ src/runtime/instance.m @@ -79,11 +79,11 @@ if (object == nil) return NULL; #ifdef OF_OBJFW_RUNTIME - objc_zero_weak_references(object); + objc_zeroWeakReferences(object); #endif if (destructSelector == NULL) destructSelector = sel_registerName(".cxx_destruct"); Index: src/runtime/ivar.m ================================================================== --- src/runtime/ivar.m +++ src/runtime/ivar.m @@ -29,33 +29,33 @@ *outCount = 0; return NULL; } - objc_global_mutex_lock(); + objc_globalMutex_lock(); count = (class->ivars != NULL ? class->ivars->count : 0); if (count == 0) { if (outCount != NULL) *outCount = 0; - objc_global_mutex_unlock(); + objc_globalMutex_unlock(); return NULL; } if ((ivars = malloc((count + 1) * sizeof(Ivar))) == NULL) - OBJC_ERROR("Not enough memory to copy ivars"); + OBJC_ERROR("Not enough memory to copy ivars!"); for (unsigned int i = 0; i < count; i++) ivars[i] = &class->ivars->ivars[i]; ivars[count] = NULL; if (outCount != NULL) *outCount = count; - objc_global_mutex_unlock(); + objc_globalMutex_unlock(); return ivars; } const char * DELETED src/runtime/library.xml Index: src/runtime/library.xml ================================================================== --- src/runtime/library.xml +++ src/runtime/library.xml @@ -1,345 +0,0 @@ - - ObjFWRT.h - private.h - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Index: src/runtime/linklib/linklib.m ================================================================== --- src/runtime/linklib/linklib.m +++ src/runtime/linklib/linklib.m @@ -11,11 +11,11 @@ * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ -/* This file is automatically generated from library.xml */ +/* This file is automatically generated from amiga-library.xml */ #include "config.h" #import "ObjFWRT.h" #import "private.h" @@ -1042,24 +1042,24 @@ return __extension__ ((bool (*)(Protocol *_Nonnull, Protocol *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 382))(protocol1, protocol2); #endif } -_Nullable objc_uncaught_exception_handler_t -objc_setUncaughtExceptionHandler(objc_uncaught_exception_handler_t _Nullable handler) +_Nullable objc_uncaught_exception_handler +objc_setUncaughtExceptionHandler(objc_uncaught_exception_handler _Nullable handler) { #if defined(OF_AMIGAOS_M68K) register struct Library *a6 __asm__("a6") = ObjFWRTBase; (void)a6; - return ((_Nullable objc_uncaught_exception_handler_t (*)(objc_uncaught_exception_handler_t _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 390))(handler); + return ((_Nullable objc_uncaught_exception_handler (*)(objc_uncaught_exception_handler _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 390))(handler); #elif defined(OF_MORPHOS) __asm__ __volatile__ ( "mr %%r12, %0" :: "r"(ObjFWRTBase) : "r12" ); - return __extension__ ((_Nullable objc_uncaught_exception_handler_t (*)(objc_uncaught_exception_handler_t _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 388))(handler); + return __extension__ ((_Nullable objc_uncaught_exception_handler (*)(objc_uncaught_exception_handler _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 388))(handler); #endif } void objc_setForwardHandler(IMP _Nullable forward, IMP _Nullable stretForward) @@ -1077,23 +1077,23 @@ __extension__ ((void (*)(IMP _Nullable, IMP _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 394))(forward, stretForward); #endif } void -objc_setEnumerationMutationHandler(objc_enumeration_mutation_handler_t _Nullable hadler) +objc_setEnumerationMutationHandler(objc_enumeration_mutation_handler _Nullable hadler) { #if defined(OF_AMIGAOS_M68K) register struct Library *a6 __asm__("a6") = ObjFWRTBase; (void)a6; - ((void (*)(objc_enumeration_mutation_handler_t _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 402))(hadler); + ((void (*)(objc_enumeration_mutation_handler _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 402))(hadler); #elif defined(OF_MORPHOS) __asm__ __volatile__ ( "mr %%r12, %0" :: "r"(ObjFWRTBase) : "r12" ); - __extension__ ((void (*)(objc_enumeration_mutation_handler_t _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 400))(hadler); + __extension__ ((void (*)(objc_enumeration_mutation_handler _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 400))(hadler); #endif } id _Nullable objc_constructInstance(Class _Nullable class, void *_Nullable bytes) @@ -1111,11 +1111,11 @@ return __extension__ ((id _Nullable (*)(Class _Nullable, void *_Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 406))(class, bytes); #endif } void -objc_exit() +objc_deinit() { #if defined(OF_AMIGAOS_M68K) register struct Library *a6 __asm__("a6") = ObjFWRTBase; (void)a6; ((void (*)())(((uintptr_t)ObjFWRTBase) - 414))(); Index: src/runtime/lookup-asm/lookup-asm-arm-elf.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-arm-elf.S +++ src/runtime/lookup-asm/lookup-asm-arm-elf.S @@ -21,17 +21,17 @@ .globl objc_msg_lookup_stret .globl objc_msg_lookup_super .globl objc_msg_lookup_super_stret .section .text -.macro generate_lookup name not_found +.macro GENERATE_LOOKUP name notFound \name: cmp r0, #0 - beq ret_nil + beq returnNilMethod tst r0, #1 - bne .Ltagged_pointer_\name + bne .LtaggedPointer_\name ldr r2, [r0, #0] ldr r2, [r2, #32] .Lmain_\name: @@ -54,67 +54,67 @@ ldrb r3, [r1, #3] ldr r2, [r2, r3, lsl #2] #endif cmp r2, #0 - beq \not_found(PLT) + beq \notFound(PLT) mov r0, r2 bx lr -.Ltagged_pointer_\name: - ldr r2, .Lgot$indirect_.Ltagged_pointer_\name +.LtaggedPointer_\name: + ldr r2, .Lgot$indirect_.LtaggedPointer_\name add r2, pc, r2 - ldr r3, .Lgot$indirect_.Ltagged_pointer_\name+4 + ldr r3, .Lgot$indirect_.LtaggedPointer_\name+4 ldr r3, [r2, r3] ldr r3, [r3] eor r0, r0, r3 and r0, r0, #0xE lsl r0, r0, #1 - ldr r3, .Lgot$indirect_.Ltagged_pointer_\name+8 + ldr r3, .Lgot$indirect_.LtaggedPointer_\name+8 ldr r3, [r2, r3] ldr r2, [r3, r0] ldr r2, [r2, #32] b .Lmain_\name .type \name, %function .size \name, .-\name -.Lgot$indirect_.Ltagged_pointer_\name: - .long _GLOBAL_OFFSET_TABLE_-(.Ltagged_pointer_\name+12) - .long objc_tagged_pointer_secret(GOT) - .long objc_tagged_pointer_classes(GOT) +.Lgot$indirect_.LtaggedPointer_\name: + .long _GLOBAL_OFFSET_TABLE_-(.LtaggedPointer_\name+12) + .long objc_taggedPointerSecret(GOT) + .long objc_taggedPointerClasses(GOT) .endm -.macro generate_lookup_super name lookup +.macro GENERATE_LOOKUP_SUPER name lookup \name: mov r2, r0 ldr r0, [r0, #0] cmp r0, #0 - beq ret_nil + beq returnNilMethod ldr r2, [r2, #4] ldr r2, [r2, #32] b .Lmain_\lookup .type \name, %function .size \name, .-\name .endm -generate_lookup objc_msg_lookup objc_method_not_found -generate_lookup objc_msg_lookup_stret objc_method_not_found_stret -generate_lookup_super objc_msg_lookup_super objc_msg_lookup -generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret +GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound +GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret +GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup +GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret -ret_nil: - adr r0, nil_method +returnNilMethod: + adr r0, nilMethod bx lr -nil_method: +nilMethod: mov r0, #0 bx lr #ifdef OF_LINUX .section .note.GNU-stack, "", %progbits #endif Index: src/runtime/lookup-asm/lookup-asm-arm64-elf.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-arm64-elf.S +++ src/runtime/lookup-asm/lookup-asm-arm64-elf.S @@ -21,16 +21,16 @@ .globl objc_msg_lookup_stret .globl objc_msg_lookup_super .globl objc_msg_lookup_super_stret .section .text -.macro generate_lookup name not_found +.macro GENERATE_LOOKUP name notFound \name: - cbz x0, ret_nil + cbz x0, returnNilMethod tst x0, #1 - b.ne .Ltagged_pointer_\name + b.ne .LtaggedPointer_\name ldr x2, [x0] ldr x2, [x2, #64] .Lmain_\name: @@ -41,58 +41,58 @@ ldrb w3, [x1, #1] ldr x2, [x2, x3, lsl #3] ldrb w3, [x1] ldr x2, [x2, x3, lsl #3] - cbz x2, \not_found + cbz x2, \notFound mov x0, x2 ret -.Ltagged_pointer_\name: - adrp x2, :got:objc_tagged_pointer_secret - ldr x2, [x2, #:got_lo12:objc_tagged_pointer_secret] +.LtaggedPointer_\name: + adrp x2, :got:objc_taggedPointerSecret + ldr x2, [x2, #:got_lo12:objc_taggedPointerSecret] ldr x2, [x2] eor x0, x0, x2 and x0, x0, #0xE lsl x0, x0, #2 - adrp x2, :got:objc_tagged_pointer_classes - ldr x2, [x2, #:got_lo12:objc_tagged_pointer_classes] + adrp x2, :got:objc_taggedPointerClasses + ldr x2, [x2, #:got_lo12:objc_taggedPointerClasses] ldr x2, [x2, x0] ldr x2, [x2, #64] b .Lmain_\name .type \name, %function .size \name, .-\name .endm -.macro generate_lookup_super name lookup +.macro GENERATE_LOOKUP_SUPER name lookup \name: mov x2, x0 ldr x0, [x0] - cbz x0, ret_nil + cbz x0, returnNilMethod ldr x2, [x2, #8] ldr x2, [x2, #64] b .Lmain_\lookup .type \name, %function .size \name, .-\name .endm -generate_lookup objc_msg_lookup objc_method_not_found -generate_lookup objc_msg_lookup_stret objc_method_not_found_stret -generate_lookup_super objc_msg_lookup_super objc_msg_lookup -generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret +GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound +GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret +GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup +GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret -ret_nil: - adr x0, nil_method +returnNilMethod: + adr x0, nilMethod ret -nil_method: +nilMethod: mov x0, #0 ret #ifdef OF_LINUX .section .note.GNU-stack, "", %progbits #endif Index: src/runtime/lookup-asm/lookup-asm-mips-elf.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-mips-elf.S +++ src/runtime/lookup-asm/lookup-asm-mips-elf.S @@ -21,16 +21,16 @@ .globl objc_msg_lookup_stret .globl objc_msg_lookup_super .globl objc_msg_lookup_super_stret .section .text -.macro generate_lookup name not_found +.macro GENERATE_LOOKUP name notFound \name: beqz $a0, 0f andi $t0, $a0, 1 - bnez $t0, .Ltagged_pointer_\name + bnez $t0, .LtaggedPointer_\name lw $t0, 0($a0) lw $t0, 32($t0) .Lmain_\name: @@ -64,21 +64,21 @@ lw $t0, 0($t0) #ifdef OF_PIC beqz $t0, 1f #else - beqz $t0, \not_found + beqz $t0, \notFound #endif move $v0, $t0 jr $ra 0: #ifdef OF_PIC - addiu $v0, $t9, nil_method-\name + addiu $v0, $t9, nilMethod-\name #else - la $v0, nil_method + la $v0, nilMethod #endif jr $ra #ifdef OF_PIC 1: @@ -85,35 +85,35 @@ lui $gp, %hi(_gp_disp) addiu $gp, $gp, %lo(_gp_disp) addu $gp, $gp, $t9 addiu $gp, $gp, 1b-\name - lw $t9, %call16(\not_found)($gp) + lw $t9, %call16(\notFound)($gp) jr $t9 #endif -.Ltagged_pointer_\name: +.LtaggedPointer_\name: #ifdef OF_PIC 0: lui $gp, %hi(_gp_disp) addiu $gp, $gp, %lo(_gp_disp) addu $gp, $gp, $t9 addiu $gp, $gp, 0b-\name - lw $t0, %got(objc_tagged_pointer_secret)($gp) + lw $t0, %got(objc_taggedPointerSecret)($gp) #else - la $t0, objc_tagged_pointer_secret + la $t0, objc_taggedPointerSecret #endif lw $t0, 0($t0) xor $t0, $a0, $t0 and $t0, $t0, 0xE sll $t0, $t0, 1 #ifdef OF_PIC - lw $t1, %got(objc_tagged_pointer_classes)($gp) + lw $t1, %got(objc_taggedPointerClasses)($gp) #else - la $t1, objc_tagged_pointer_classes + la $t1, objc_taggedPointerClasses #endif addu $t0, $t1, $t0 ld $t0, ($t0) ld $t0, 32($t0) @@ -120,11 +120,11 @@ b .Lmain_\name .type \name, %function .size \name, .-\name .endm -.macro generate_lookup_super name lookup +.macro GENERATE_LOOKUP_SUPER name lookup \name: move $t0, $a0 lw $a0, 0($a0) beqz $a0, 0f @@ -134,26 +134,26 @@ addiu $t9, $t9, \lookup-\name b .Lmain_\lookup 0: #ifdef OF_PIC - addiu $v0, $t9, nil_method-\name + addiu $v0, $t9, nilMethod-\name #else - la $v0, nil_method + la $v0, nilMethod #endif jr $ra .type \name, %function .size \name, .-\name .endm -generate_lookup objc_msg_lookup objc_method_not_found -generate_lookup objc_msg_lookup_stret objc_method_not_found_stret -generate_lookup_super objc_msg_lookup_super objc_msg_lookup -generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret +GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound +GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret +GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup +GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret -nil_method: +nilMethod: move $v0, $zero jr $ra #ifdef OF_LINUX .section .note.GNU-stack, "", %progbits #endif Index: src/runtime/lookup-asm/lookup-asm-mips64-n64-elf.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-mips64-n64-elf.S +++ src/runtime/lookup-asm/lookup-asm-mips64-n64-elf.S @@ -21,16 +21,16 @@ .globl objc_msg_lookup_stret .globl objc_msg_lookup_super .globl objc_msg_lookup_super_stret .section .text -.macro generate_lookup name not_found +.macro GENERATE_LOOKUP name notFound \name: beqz $a0, 0f andi $t0, $a0, 1 - bnez $t0, .Ltagged_pointer_\name + bnez $t0, .LtaggedPointer_\name ld $t0, ($a0) ld $t0, 64($t0) .Lmain_\name: @@ -70,42 +70,42 @@ 0: lui $v0, %hi(%neg(%gp_rel(\name))) daddiu $v0, $v0, %lo(%neg(%gp_rel(\name))) daddu $v0, $v0, $t9 - ld $v0, %got_disp(nil_method)($v0) + ld $v0, %got_disp(nilMethod)($v0) jr $ra 1: lui $t0, %hi(%neg(%gp_rel(\name))) daddiu $t0, $t0, %lo(%neg(%gp_rel(\name))) daddu $t0, $t0, $t9 - ld $t9, %got_disp(\not_found)($t0) + ld $t9, %got_disp(\notFound)($t0) jr $t9 -.Ltagged_pointer_\name: +.LtaggedPointer_\name: lui $t0, %hi(%neg(%gp_rel(\name))) daddiu $t0, $t0, %lo(%neg(%gp_rel(\name))) daddu $t0, $t0, $t9 - ld $t1, %got_disp(objc_tagged_pointer_secret)($t0) + ld $t1, %got_disp(objc_taggedPointerSecret)($t0) ld $t1, 0($t1) xor $t1, $a0, $t1 and $t1, $t1, 0xE dsll $t1, $t1, 2 - ld $t0, %got_disp(objc_tagged_pointer_classes)($t0) + ld $t0, %got_disp(objc_taggedPointerClasses)($t0) daddu $t0, $t0, $t1 ld $t0, ($t0) ld $t0, 64($t0) b .Lmain_\name .type \name, %function .size \name, .-\name .endm -.macro generate_lookup_super name lookup +.macro GENERATE_LOOKUP_SUPER name lookup \name: move $t0, $a0 ld $a0, ($a0) beqz $a0, 0f @@ -117,23 +117,23 @@ 0: lui $v0, %hi(%neg(%gp_rel(\name))) daddiu $v0, $v0, %lo(%neg(%gp_rel(\name))) daddu $v0, $v0, $t9 - ld $v0, %got_disp(nil_method)($v0) + ld $v0, %got_disp(nilMethod)($v0) jr $ra .type \name, %function .size \name, .-\name .endm -generate_lookup objc_msg_lookup objc_method_not_found -generate_lookup objc_msg_lookup_stret objc_method_not_found_stret -generate_lookup_super objc_msg_lookup_super objc_msg_lookup -generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret +GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound +GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret +GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup +GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret -nil_method: +nilMethod: move $v0, $zero jr $ra #ifdef OF_LINUX .section .note.GNU-stack, "", %progbits #endif Index: src/runtime/lookup-asm/lookup-asm-powerpc-elf.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-powerpc-elf.S +++ src/runtime/lookup-asm/lookup-asm-powerpc-elf.S @@ -21,17 +21,17 @@ .globl objc_msg_lookup_stret .globl objc_msg_lookup_super .globl objc_msg_lookup_super_stret .section .text -.macro generate_lookup name not_found +.macro GENERATE_LOOKUP name notFound \name: cmpwi %r3, 0 - beq- ret_nil + beq- returnNilMethod andi. %r0, %r3, 1 - bne- .Ltagged_pointer_\name + bne- .LtaggedPointer_\name lwz %r5, 0(%r3) lwz %r5, 32(%r5) .Lmain_\name: @@ -65,109 +65,109 @@ 0: mflr %r30 addis %r30, %r30, .Lbiased_got2-0b@ha addi %r30, %r30, .Lbiased_got2-0b@l - lwz %r0, .Lgot_\not_found-.Lbiased_got2(%r30) + lwz %r0, .Lgot_\notFound-.Lbiased_got2(%r30) mtctr %r0 lwz %r30, 8(%r1) lwz %r0, 20(%r1) addi %r1, %r1, 16 mtlr %r0 bctr #else - b \not_found + b \notFound #endif -.Ltagged_pointer_\name: +.LtaggedPointer_\name: #if defined(OF_PIC) mflr %r7 bl 0f 0: mflr %r6 mtlr %r7 addis %r6, %r6, .Lbiased_got2-0b@ha addi %r6, %r6, .Lbiased_got2-0b@l - lwz %r5, .Lgot_objc_tagged_pointer_secret-.Lbiased_got2(%r6) + lwz %r5, .Lgot_objc_taggedPointerSecret-.Lbiased_got2(%r6) lwz %r5, 0(%r5) #elif defined(OF_BASEREL) - addis %r5, %r13, objc_tagged_pointer_secret@drel@ha - lwz %r5, objc_tagged_pointer_secret@drel@l(%r5) + addis %r5, %r13, objc_taggedPointerSecret@drel@ha + lwz %r5, objc_taggedPointerSecret@drel@l(%r5) #else - lis %r5, objc_tagged_pointer_secret@ha - lwz %r5, objc_tagged_pointer_secret@l(%r5) + lis %r5, objc_taggedPointerSecret@ha + lwz %r5, objc_taggedPointerSecret@l(%r5) #endif xor %r5, %r3, %r5 rlwinm %r5, %r5, 1, 0x1C #if defined(OF_PIC) - lwz %r6, .Lgot_objc_tagged_pointer_classes-.Lbiased_got2(%r6) + lwz %r6, .Lgot_objc_taggedPointerClasses-.Lbiased_got2(%r6) #elif defined(OF_BASEREL) - addis %r6, %r13, objc_tagged_pointer_classes@drel@ha - addi %r6, %r6, objc_tagged_pointer_classes@drel@l + addis %r6, %r13, objc_taggedPointerClasses@drel@ha + addi %r6, %r6, objc_taggedPointerClasses@drel@l #else - lis %r6, objc_tagged_pointer_classes@ha - addi %r6, %r6, objc_tagged_pointer_classes@l + lis %r6, objc_taggedPointerClasses@ha + addi %r6, %r6, objc_taggedPointerClasses@l #endif lwzx %r5, %r6, %r5 lwz %r5, 32(%r5) b .Lmain_\name .type \name, @function .size \name, .-\name .endm -.macro generate_lookup_super name lookup +.macro GENERATE_LOOKUP_SUPER name lookup \name: mr %r5, %r3 lwz %r3, 0(%r3) cmpwi %r3, 0 - beq- ret_nil + beq- returnNilMethod lwz %r5, 4(%r5) lwz %r5, 32(%r5) b .Lmain_\lookup .type \name, @function .size \name, .-\name .endm -generate_lookup objc_msg_lookup objc_method_not_found -generate_lookup objc_msg_lookup_stret objc_method_not_found_stret -generate_lookup_super objc_msg_lookup_super objc_msg_lookup -generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret - -ret_nil: - mflr %r0 - bl get_pc +GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound +GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret +GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup +GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret + +returnNilMethod: + mflr %r0 + bl getPC mtlr %r0 0: - addi %r3, %r3, nil_method-0b + addi %r3, %r3, nilMethod-0b blr -nil_method: +nilMethod: li %r3, 0 blr -get_pc: +getPC: mflr %r3 blr #ifdef OF_PIC .section .got2, "aw" .Lbiased_got2 = .+0x8000 -.Lgot_objc_method_not_found: - .long objc_method_not_found -.Lgot_objc_method_not_found_stret: - .long objc_method_not_found_stret -.Lgot_objc_tagged_pointer_secret: - .long objc_tagged_pointer_secret -.Lgot_objc_tagged_pointer_classes: - .long objc_tagged_pointer_classes +.Lgot_objc_methodNotFound: + .long objc_methodNotFound +.Lgot_objc_methodNotFound_stret: + .long objc_methodNotFound_stret +.Lgot_objc_taggedPointerSecret: + .long objc_taggedPointerSecret +.Lgot_objc_taggedPointerClasses: + .long objc_taggedPointerClasses #endif #ifdef OF_LINUX .section .note.GNU-stack, "", @progbits #endif ADDED src/runtime/lookup-asm/lookup-asm-powerpc64-elf.S Index: src/runtime/lookup-asm/lookup-asm-powerpc64-elf.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-powerpc64-elf.S +++ src/runtime/lookup-asm/lookup-asm-powerpc64-elf.S @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2008-2021 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#include "platform.h" + +.globl objc_msg_lookup +.globl objc_msg_lookup_stret +.globl objc_msg_lookup_super +.globl objc_msg_lookup_super_stret + +.section .text +.macro GENERATE_LOOKUP name notFound +.section .opd, "aw", @progbits +\name: + .p2align 3 + .quad .Lbegin_\name + .quad .TOC.@tocbase + .quad 0 +.text +.Lbegin_\name: + cmpdi %r3, 0 + beq- .LreturnNilMethod + + andi. %r0, %r3, 1 + bne- .LtaggedPointer_\name + + ld %r5, 0(%r3) + ld %r5, 64(%r5) + +.Lmain_\name: + ld %r8, 0(%r4) +#ifdef OF_SELUID24 + rlwinm %r6, %r8, 19, 0x7F8 +#endif + rlwinm %r7, %r8, 27, 0x7F8 + rlwinm %r8, %r8, 3, 0x7F8 + +#ifdef OF_SELUID24 + ldx %r5, %r5, %r6 +#endif + ldx %r5, %r5, %r7 + ldx %r5, %r5, %r8 + + cmpdi %r5, 0 + beq- 0f + + mr %r3, %r5 + blr + +0: + mflr %r0 + std %r0, 16(%r1) + stdu %r1, -112(%r1) + bl \notFound + nop + addi %r1, %r1, 112 + ld %r0, 16(%r1) + mtlr %r0 + blr + +.LtaggedPointer_\name: + addis %r5, %r2, objc_taggedPointerSecret@toc@ha + ld %r5, objc_taggedPointerSecret@toc@l(%r5) + xor %r5, %r3, %r5 + rlwinm %r5, %r5, 2, 0x38 + + addis %r6, %r2, objc_taggedPointerClasses@toc@ha + addi %r6, %r6, objc_taggedPointerClasses@toc@l + ldx %r5, %r6, %r5 + ld %r5, 64(%r5) + + b .Lmain_\name +.type \name, @function +.size \name, .-.Lbegin_\name +.endm + +.macro GENERATE_LOOKUP_SUPER name lookup +.section .opd, "aw", @progbits +\name: + .p2align 3 + .quad .Lbegin_\name + .quad .TOC.@tocbase + .quad 0 +.text +.Lbegin_\name: + mr %r5, %r3 + ld %r3, 0(%r3) + cmpdi %r3, 0 + beq- .LreturnNilMethod + + ld %r5, 8(%r5) + ld %r5, 64(%r5) + + b .Lmain_\lookup +.type \name, @function +.size \name, .-.Lbegin_\name +.endm + +GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound +GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret +GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup +GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret + +.LreturnNilMethod: + addis %r3, %r2, nilMethod@toc@ha + addi %r3, %r3, nilMethod@toc@l + blr + +.section .opd, "aw", @progbits +nilMethod: + .p2align 3 + .quad .Lbegin_nilMethod + .quad .TOC.@tocbase + .quad 0 +.text +.Lbegin_nilMethod: + li %r3, 0 + blr +.type nilMethod, @function +.size nilMethod, .-.Lbegin_nilMethod + +#ifdef OF_LINUX +.section .note.GNU-stack, "", @progbits +#endif Index: src/runtime/lookup-asm/lookup-asm-sparc-elf.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-sparc-elf.S +++ src/runtime/lookup-asm/lookup-asm-sparc-elf.S @@ -21,16 +21,16 @@ .globl objc_msg_lookup_stret .globl objc_msg_lookup_super .globl objc_msg_lookup_super_stret .section .text -.macro generate_lookup name not_found +.macro GENERATE_LOOKUP name notFound \name: tst %o0 - bz ret_nil + bz returnNilMethod btst 1, %o0 - bnz .Ltagged_pointer_\name + bnz .LtaggedPointer_\name nop ld [%o0], %o2 ld [%o2 + 32], %o2 @@ -60,14 +60,14 @@ retl mov %o2, %o0 0: mov %o7, %g1 - call \not_found + call \notFound mov %g1, %o7 -.Ltagged_pointer_\name: +.LtaggedPointer_\name: #ifdef OF_PIC mov %o7, %g1 sethi %hi(_GLOBAL_OFFSET_TABLE_ - 4), %o3 call 0f or %o3, %lo(_GLOBAL_OFFSET_TABLE_ + 4), %o3 @@ -74,22 +74,22 @@ 0: add %o7, %o3, %o3 mov %g1, %o7 #endif - sethi %hi(objc_tagged_pointer_secret), %o2 - or %o2, %lo(objc_tagged_pointer_secret), %o2 + sethi %hi(objc_taggedPointerSecret), %o2 + or %o2, %lo(objc_taggedPointerSecret), %o2 #ifdef OF_PIC ld [%o3 + %o2], %o2 #endif ld [%o2], %o2 xor %o0, %o2, %o0 and %o0, 0xE, %o0 sll %o0, 1, %o0 - sethi %hi(objc_tagged_pointer_classes), %o2 - or %o2, %lo(objc_tagged_pointer_classes), %o2 + sethi %hi(objc_taggedPointerClasses), %o2 + or %o2, %lo(objc_taggedPointerClasses), %o2 #ifdef OF_PIC ld [%o3 + %o2], %o2 #endif ld [%o2 + %o0], %o2 @@ -97,53 +97,53 @@ ld [%o2 + 32], %o2 .type \name, %function .size \name, .-\name .endm -.macro generate_lookup_super name lookup +.macro GENERATE_LOOKUP_SUPER name lookup \name: mov %o0, %o2 ld [%o0], %o0 cmp %o0, 0 - be ret_nil + be returnNilMethod nop ld [%o2 + 4], %o2 ba .Lmain_\lookup ld [%o2 + 32], %o2 .type \name, %function .size \name, .-\name .endm -generate_lookup objc_msg_lookup objc_method_not_found -generate_lookup objc_msg_lookup_stret objc_method_not_found_stret -generate_lookup_super objc_msg_lookup_super objc_msg_lookup -generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret +GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound +GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret +GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup +GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret -ret_nil: +returnNilMethod: #ifdef OF_PIC mov %o7, %g1 sethi %hi(_GLOBAL_OFFSET_TABLE_ - 4), %o1 call 0f add %o1, %lo(_GLOBAL_OFFSET_TABLE_ + 4), %o1 0: add %o7, %o1, %o1 - sethi %hi(nil_method), %o0 - or %o0, %lo(nil_method), %o0 + sethi %hi(nilMethod), %o0 + or %o0, %lo(nilMethod), %o0 jmpl %g1 + 8, %g0 ld [%o1 + %o0], %o0 #else - sethi %hi(nil_method), %o0 + sethi %hi(nilMethod), %o0 retl - or %o0, %lo(nil_method), %o0 + or %o0, %lo(nilMethod), %o0 #endif -nil_method: +nilMethod: retl clr %o0 #ifdef OF_LINUX .section .note.GNU-stack, "", %progbits #endif Index: src/runtime/lookup-asm/lookup-asm-sparc64-elf.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-sparc64-elf.S +++ src/runtime/lookup-asm/lookup-asm-sparc64-elf.S @@ -21,15 +21,15 @@ .globl objc_msg_lookup_stret .globl objc_msg_lookup_super .globl objc_msg_lookup_super_stret .section .text -.macro generate_lookup name not_found +.macro GENERATE_LOOKUP name notFound \name: - brz,pn %o0, ret_nil + brz,pn %o0, returnNilMethod and %o0, 1, %o2 - brnz,pn %o2, .Ltagged_pointer_\name + brnz,pn %o2, .LtaggedPointer_\name nop ldx [%o0], %o2 ldx [%o2 + 64], %o2 @@ -58,14 +58,14 @@ retl mov %o2, %o0 0: mov %o7, %g1 - call \not_found + call \notFound mov %g1, %o7 -.Ltagged_pointer_\name: +.LtaggedPointer_\name: #ifdef OF_PIC mov %o7, %g1 sethi %hi(_GLOBAL_OFFSET_TABLE_ - 4), %o3 call 0f or %o3, %lo(_GLOBAL_OFFSET_TABLE_ + 4), %o3 @@ -72,22 +72,22 @@ 0: add %o7, %o3, %o3 mov %g1, %o7 #endif - sethi %hi(objc_tagged_pointer_secret), %o2 - or %o2, %lo(objc_tagged_pointer_secret), %o2 + sethi %hi(objc_taggedPointerSecret), %o2 + or %o2, %lo(objc_taggedPointerSecret), %o2 #ifdef OF_PIC ldx [%o3 + %o2], %o2 #endif ldx [%o2], %o2 xor %o0, %o2, %o0 and %o0, 0xE, %o0 sll %o0, 2, %o0 - sethi %hi(objc_tagged_pointer_classes), %o2 - or %o2, %lo(objc_tagged_pointer_classes), %o2 + sethi %hi(objc_taggedPointerClasses), %o2 + or %o2, %lo(objc_taggedPointerClasses), %o2 #ifdef OF_PIC ldx [%o3 + %o2], %o2 #endif ldx [%o2 + %o0], %o2 @@ -95,52 +95,52 @@ ldx [%o2 + 64], %o2 .type \name, %function .size \name, .-\name .endm -.macro generate_lookup_super name lookup +.macro GENERATE_LOOKUP_SUPER name lookup \name: mov %o0, %o2 ldx [%o0], %o0 - brz,pn %o0, ret_nil + brz,pn %o0, returnNilMethod nop ldx [%o2 + 8], %o2 ba .Lmain_\lookup ldx [%o2 + 64], %o2 .type \name, %function .size \name, .-\name .endm -generate_lookup objc_msg_lookup objc_method_not_found -generate_lookup objc_msg_lookup_stret objc_method_not_found_stret -generate_lookup_super objc_msg_lookup_super objc_msg_lookup -generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret +GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound +GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret +GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup +GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret -ret_nil: +returnNilMethod: #ifdef OF_PIC mov %o7, %g1 sethi %hi(_GLOBAL_OFFSET_TABLE_ - 4), %o1 call 0f or %o1, %lo(_GLOBAL_OFFSET_TABLE_ + 4), %o1 0: add %o7, %o1, %o1 - sethi %hi(nil_method), %o0 - or %o0, %lo(nil_method), %o0 + sethi %hi(nilMethod), %o0 + or %o0, %lo(nilMethod), %o0 jmpl %g1 + 8, %g0 ldx [%o1 + %o0], %o0 #else - sethi %hi(nil_method), %o0 + sethi %hi(nilMethod), %o0 retl - or %o0, %lo(nil_method), %o0 + or %o0, %lo(nilMethod), %o0 #endif -nil_method: +nilMethod: retl clr %o0 #ifdef OF_LINUX .section .note.GNU-stack, "", %progbits #endif Index: src/runtime/lookup-asm/lookup-asm-x86-elf.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-x86-elf.S +++ src/runtime/lookup-asm/lookup-asm-x86-elf.S @@ -21,18 +21,18 @@ .globl objc_msg_lookup_stret .globl objc_msg_lookup_super .globl objc_msg_lookup_super_stret .section .text -.macro generate_lookup name not_found +.macro GENERATE_LOOKUP name notFound \name: movl 4(%esp), %edx testl %edx, %edx - jz ret_nil + jz returnNilMethod testb $1, %dl - jnz .Ltagged_pointer_\name + jnz .LtaggedPointer_\name movl (%edx), %edx movl 32(%edx), %edx .Lmain_\name: @@ -51,65 +51,65 @@ jz 0f ret 0: - call get_eip + call getEIP addl $_GLOBAL_OFFSET_TABLE_, %eax - lea \not_found@GOTOFF(%eax), %eax + lea \notFound@GOTOFF(%eax), %eax jmp *%eax -.Ltagged_pointer_\name: - call get_eip +.LtaggedPointer_\name: + call getEIP addl $_GLOBAL_OFFSET_TABLE_, %eax - leal objc_tagged_pointer_secret@GOTOFF(%eax), %ecx + leal objc_taggedPointerSecret@GOTOFF(%eax), %ecx xorl (%ecx), %edx andb $0xE, %dl movzbl %dl, %edx - leal objc_tagged_pointer_classes@GOTOFF(%eax), %eax + leal objc_taggedPointerClasses@GOTOFF(%eax), %eax movl (%eax,%edx,2), %edx movl 32(%edx), %edx jmp .Lmain_\name .type \name, %function .size \name, .-\name .endm -.macro generate_lookup_super name lookup +.macro GENERATE_LOOKUP_SUPER name lookup \name: movl 4(%esp), %edx movl (%edx), %eax testl %eax, %eax - jz ret_nil + jz returnNilMethod movl %eax, 4(%esp) mov 4(%edx), %edx mov 32(%edx), %edx jmp .Lmain_\lookup .type \name, %function .size \name, .-\name .endm -generate_lookup objc_msg_lookup objc_method_not_found -generate_lookup objc_msg_lookup_stret objc_method_not_found_stret -generate_lookup_super objc_msg_lookup_super objc_msg_lookup -generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret - -ret_nil: - call get_eip - addl $_GLOBAL_OFFSET_TABLE_, %eax - leal nil_method@GOTOFF(%eax), %eax +GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound +GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret +GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup +GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret + +returnNilMethod: + call getEIP + addl $_GLOBAL_OFFSET_TABLE_, %eax + leal nilMethod@GOTOFF(%eax), %eax ret -nil_method: +nilMethod: xorl %eax, %eax ret -get_eip: +getEIP: movl (%esp), %eax ret #ifdef OF_LINUX .section .note.GNU-stack, "", %progbits #endif Index: src/runtime/lookup-asm/lookup-asm-x86-win32.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-x86-win32.S +++ src/runtime/lookup-asm/lookup-asm-x86-win32.S @@ -19,18 +19,18 @@ .globl _objc_msg_lookup_stret .globl _objc_msg_lookup_super .globl _objc_msg_lookup_super_stret .section .text -.macro generate_lookup name not_found +.macro GENERATE_LOOKUP name notFound \name: movl 4(%esp), %edx testl %edx, %edx - jz ret_nil + jz returnNilMethod testb $1, %dl - jnz .Ltagged_pointer_\name + jnz .LtaggedPointer_\name movl (%edx), %edx movl 32(%edx), %edx .Lmain_\name: @@ -44,35 +44,35 @@ movl (%edx,%ecx,4), %edx movzbl (%eax), %ecx movl (%edx,%ecx,4), %eax testl %eax, %eax - jz \not_found + jz \notFound ret -.Ltagged_pointer_\name: - xorl _objc_tagged_pointer_secret, %edx +.LtaggedPointer_\name: + xorl _objc_taggedPointerSecret, %edx andb $0xE, %dl movzbl %dl, %edx - movl _objc_tagged_pointer_classes(,%edx,2), %edx + movl _objc_taggedPointerClasses(,%edx,2), %edx movl 32(%edx), %edx jmp .Lmain_\name .def \name .scl 2 .type 32 .endef .endm -.macro generate_lookup_super name lookup +.macro GENERATE_LOOKUP_SUPER name lookup \name: movl 4(%esp), %edx movl (%edx), %eax test %eax, %eax - jz ret_nil + jz returnNilMethod movl %eax, 4(%esp) movl 4(%edx), %edx movl 32(%edx), %edx jmp .Lmain_\lookup @@ -80,17 +80,17 @@ .scl 2 .type 32 .endef .endm -generate_lookup _objc_msg_lookup _objc_method_not_found -generate_lookup _objc_msg_lookup_stret _objc_method_not_found_stret -generate_lookup_super _objc_msg_lookup_super _objc_msg_lookup -generate_lookup_super _objc_msg_lookup_super_stret _objc_msg_lookup_stret +GENERATE_LOOKUP _objc_msg_lookup _objc_methodNotFound +GENERATE_LOOKUP _objc_msg_lookup_stret _objc_methodNotFound_stret +GENERATE_LOOKUP_SUPER _objc_msg_lookup_super _objc_msg_lookup +GENERATE_LOOKUP_SUPER _objc_msg_lookup_super_stret _objc_msg_lookup_stret -ret_nil: - movl $nil_method, %eax +returnNilMethod: + movl $nilMethod, %eax ret -nil_method: +nilMethod: xorl %eax, %eax ret Index: src/runtime/lookup-asm/lookup-asm-x86_64-elf.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-x86_64-elf.S +++ src/runtime/lookup-asm/lookup-asm-x86_64-elf.S @@ -21,17 +21,17 @@ .globl objc_msg_lookup_stret .globl objc_msg_lookup_super .globl objc_msg_lookup_super_stret .section .text -.macro generate_lookup name not_found +.macro GENERATE_LOOKUP name notFound \name: testq %rdi, %rdi - jz ret_nil + jz returnNilMethod testb $1, %dil - jnz .Ltagged_pointer_\name + jnz .LtaggedPointer_\name movq (%rdi), %r8 movq 64(%r8), %r8 .Lmain_\name: @@ -45,54 +45,54 @@ #endif movq (%r8,%rcx,8), %r8 movq (%r8,%rdx,8), %rax testq %rax, %rax - jz \not_found@PLT + jz \notFound@PLT ret -.Ltagged_pointer_\name: - movq objc_tagged_pointer_secret@GOTPCREL(%rip), %rax +.LtaggedPointer_\name: + movq objc_taggedPointerSecret@GOTPCREL(%rip), %rax xorq (%rax), %rdi andb $0xE, %dil movzbl %dil, %r8d - movq objc_tagged_pointer_classes@GOTPCREL(%rip), %rax + movq objc_taggedPointerClasses@GOTPCREL(%rip), %rax movq (%rax,%r8,4), %r8 movq 64(%r8), %r8 jmp .Lmain_\name .type \name, %function .size \name, .-\name .endm -.macro generate_lookup_super name lookup +.macro GENERATE_LOOKUP_SUPER name lookup \name: movq %rdi, %r8 movq (%rdi), %rdi testq %rdi, %rdi - jz ret_nil + jz returnNilMethod movq 8(%r8), %r8 movq 64(%r8), %r8 jmp .Lmain_\lookup .type \name, %function .size \name, .-\name .endm -generate_lookup objc_msg_lookup objc_method_not_found -generate_lookup objc_msg_lookup_stret objc_method_not_found_stret -generate_lookup_super objc_msg_lookup_super objc_msg_lookup -generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret +GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound +GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret +GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup +GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret -ret_nil: - leaq nil_method(%rip), %rax +returnNilMethod: + leaq nilMethod(%rip), %rax ret -nil_method: +nilMethod: xorq %rax, %rax ret #ifdef OF_LINUX .section .note.GNU-stack, "", %progbits #endif Index: src/runtime/lookup-asm/lookup-asm-x86_64-win64.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-x86_64-win64.S +++ src/runtime/lookup-asm/lookup-asm-x86_64-win64.S @@ -19,17 +19,17 @@ .globl objc_msg_lookup_stret .globl objc_msg_lookup_super .globl objc_msg_lookup_super_stret .section .text -.macro generate_lookup name not_found +.macro GENERATE_LOOKUP name notFound \name: testq %rcx, %rcx - jz ret_nil + jz returnNilMethod testb $1, %cl - jnz .Ltagged_pointer_\name + jnz .LtaggedPointer_\name movq (%rcx), %r8 movq 56(%r8), %r8 .Lmain_\name: @@ -53,18 +53,18 @@ ret 0: movq %r10, %rcx movq %r11, %rdx - jmp \not_found + jmp \notFound -.Ltagged_pointer_\name: - xorq objc_tagged_pointer_secret(%rip), %rcx +.LtaggedPointer_\name: + xorq objc_taggedPointerSecret(%rip), %rcx andb $0xE, %cl movzbl %cl, %r8d - leaq objc_tagged_pointer_classes(%rip), %rax + leaq objc_taggedPointerClasses(%rip), %rax movq (%rax,%r8,4), %r8 movq 56(%r8), %r8 jmp .Lmain_\name .def \name @@ -71,16 +71,16 @@ .scl 2 .type 32 .endef .endm -.macro generate_lookup_super name lookup +.macro GENERATE_LOOKUP_SUPER name lookup \name: movq %rcx, %r8 movq (%rcx), %rcx testq %rcx, %rcx - jz ret_nil + jz returnNilMethod movq 8(%r8), %r8 movq 56(%r8), %r8 jmp .Lmain_\lookup .def \name @@ -87,17 +87,17 @@ .scl 2 .type 32 .endef .endm -generate_lookup objc_msg_lookup objc_method_not_found -generate_lookup objc_msg_lookup_stret objc_method_not_found_stret -generate_lookup_super objc_msg_lookup_super objc_msg_lookup -generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret +GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound +GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret +GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup +GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret -ret_nil: - leaq nil_method(%rip), %rax +returnNilMethod: + leaq nilMethod(%rip), %rax ret -nil_method: +nilMethod: xorq %rax, %rax ret Index: src/runtime/lookup-asm/lookup-asm.S ================================================================== --- src/runtime/lookup-asm/lookup-asm.S +++ src/runtime/lookup-asm/lookup-asm.S @@ -24,11 +24,13 @@ # include "lookup-asm-x86-elf.S" # elif defined(OF_ARM64) # include "lookup-asm-arm64-elf.S" # elif defined(OF_ARM) # include "lookup-asm-arm-elf.S" -# elif defined(OF_POWERPC) +# elif defined(OF_POWERPC64) && (!defined(_CALL_ELF) || _CALL_ELF == 1) +# include "lookup-asm-powerpc64-elf.S" +# elif defined(OF_POWERPC) && (!defined(_CALL_ELF) || _CALL_ELF == 1) # include "lookup-asm-powerpc-elf.S" # elif defined(OF_MIPS64_N64) # include "lookup-asm-mips64-n64-elf.S" # elif defined(OF_MIPS) # include "lookup-asm-mips-elf.S" Index: src/runtime/lookup.m ================================================================== --- src/runtime/lookup.m +++ src/runtime/lookup.m @@ -39,15 +39,16 @@ if (!(object_getClass(object)->info & OBJC_CLASS_INFO_INITIALIZED)) { Class class = (isClass ? (Class)object : object_getClass(object)); - objc_initialize_class(class); + objc_initializeClass(class); if (!(class->info & OBJC_CLASS_INFO_SETUP)) - OBJC_ERROR("Could not dispatch message for incomplete " - "class %s!", class_getName(class)); + OBJC_ERROR("Could not dispatch message %s for " + "incomplete class %s!", + sel_getName(selector), class_getName(class)); /* * We don't need to handle the case that super was called. * The reason for this is that a call to super is not possible * before a message to the class has been sent and it thus has @@ -95,18 +96,18 @@ (isClass ? '+' : '-'), sel_getName(selector), object_getClassName(object)); } IMP -objc_method_not_found(id object, SEL selector) +objc_methodNotFound(id object, SEL selector) { return commonMethodNotFound(object, selector, objc_msg_lookup, forwardHandler); } IMP -objc_method_not_found_stret(id object, SEL selector) +objc_methodNotFound_stret(id object, SEL selector) { return commonMethodNotFound(object, selector, objc_msg_lookup_stret, stretForwardHandler); } @@ -121,11 +122,11 @@ class_respondsToSelector(Class class, SEL selector) { if (class == Nil) return false; - return (objc_dtable_get(class->DTable, + return (objc_dtable_get(class->dTable, (uint32_t)selector->UID) != (IMP)0); } #ifndef OF_ASM_LOOKUP static id @@ -140,11 +141,11 @@ IMP imp; if (object == nil) return (IMP)nilMethod; - imp = objc_dtable_get(object_getClass(object)->DTable, + imp = objc_dtable_get(object_getClass(object)->dTable, (uint32_t)selector->UID); if (imp == (IMP)0) return notFound(object, selector); @@ -152,17 +153,17 @@ } IMP objc_msg_lookup(id object, SEL selector) { - return commonLookup(object, selector, objc_method_not_found); + return commonLookup(object, selector, objc_methodNotFound); } IMP objc_msg_lookup_stret(id object, SEL selector) { - return commonLookup(object, selector, objc_method_not_found_stret); + return commonLookup(object, selector, objc_methodNotFound_stret); } static OF_INLINE IMP commonSuperLookup(struct objc_super *super, SEL selector, IMP (*notFound)(id, SEL)) @@ -170,11 +171,11 @@ IMP imp; if (super->self == nil) return (IMP)nilMethod; - imp = objc_dtable_get(super->class->DTable, (uint32_t)selector->UID); + imp = objc_dtable_get(super->class->dTable, (uint32_t)selector->UID); if (imp == (IMP)0) return notFound(super->self, selector); return imp; @@ -181,14 +182,14 @@ } IMP objc_msg_lookup_super(struct objc_super *super, SEL selector) { - return commonSuperLookup(super, selector, objc_method_not_found); + return commonSuperLookup(super, selector, objc_methodNotFound); } IMP objc_msg_lookup_super_stret(struct objc_super *super, SEL selector) { - return commonSuperLookup(super, selector, objc_method_not_found_stret); + return commonSuperLookup(super, selector, objc_methodNotFound_stret); } #endif Index: src/runtime/method.m ================================================================== --- src/runtime/method.m +++ src/runtime/method.m @@ -30,21 +30,21 @@ *outCount = 0; return NULL; } - objc_global_mutex_lock(); + objc_globalMutex_lock(); count = 0; for (iter = class->methodList; iter != NULL; iter = iter->next) count += iter->count; if (count == 0) { if (outCount != NULL) *outCount = 0; - objc_global_mutex_unlock(); + objc_globalMutex_unlock(); return NULL; } if ((methods = malloc((count + 1) * sizeof(Method))) == NULL) OBJC_ERROR("Not enough memory to copy methods"); @@ -51,17 +51,20 @@ i = 0; for (iter = class->methodList; iter != NULL; iter = iter->next) for (unsigned int j = 0; j < iter->count; j++) methods[i++] = &iter->methods[j]; - OFEnsure(i == count); + + if (i != count) + OBJC_ERROR("Fatal internal inconsistency!"); + methods[count] = NULL; if (outCount != NULL) *outCount = count; - objc_global_mutex_unlock(); + objc_globalMutex_unlock(); return methods; } SEL Index: src/runtime/misc.m ================================================================== --- src/runtime/misc.m +++ src/runtime/misc.m @@ -35,11 +35,11 @@ # include # undef Class # undef __NOLIBBASE__ #endif -static objc_enumeration_mutation_handler_t enumerationMutationHandler = NULL; +static objc_enumeration_mutation_handler enumerationMutationHandler = NULL; void objc_enumerationMutation(id object) { if (enumerationMutationHandler != NULL) @@ -47,27 +47,27 @@ else OBJC_ERROR("Object was mutated during enumeration!"); } void -objc_setEnumerationMutationHandler(objc_enumeration_mutation_handler_t handler) +objc_setEnumerationMutationHandler(objc_enumeration_mutation_handler handler) { enumerationMutationHandler = handler; } void objc_error(const char *title, const char *format, ...) { #if defined(OF_WINDOWS) || defined(OF_AMIGAOS) -# define BUF_LEN 512 - char message[BUF_LEN]; +# define messageLen 512 + char message[messageLen]; int status; va_list args; va_start(args, format); - status = vsnprintf(message, BUF_LEN, format, args); - if (status <= 0 || status >= BUF_LEN) + status = vsnprintf(message, messageLen, format, args); + if (status <= 0 || status >= messageLen) message[0] = '\0'; va_end(args); # undef BUF_LEN #endif DELETED src/runtime/morphos-clib.h Index: src/runtime/morphos-clib.h ================================================================== --- src/runtime/morphos-clib.h +++ src/runtime/morphos-clib.h @@ -1,92 +0,0 @@ -/* The following function is only for the linklib. */ -bool glue_objc_init(unsigned int, struct objc_libc *); -void glue___objc_exec_class(struct objc_module *); -IMP glue_objc_msg_lookup(id, SEL); -IMP glue_objc_msg_lookup_stret(id, SEL); -IMP glue_objc_msg_lookup_super(struct objc_super *, SEL); -IMP glue_objc_msg_lookup_super_stret(struct objc_super *, SEL); -Class glue_objc_lookUpClass(const char *); -Class glue_objc_getClass(const char *); -Class glue_objc_getRequiredClass(const char *); -Class glue_objc_lookup_class(const char *); -Class glue_objc_get_class(const char *); -void glue_objc_exception_throw(id); -int glue_objc_sync_enter(id); -int glue_objc_sync_exit(id); -id glue_objc_getProperty(id, SEL, ptrdiff_t, bool); -void glue_objc_setProperty(id, SEL, ptrdiff_t, id, bool, signed char); -void glue_objc_getPropertyStruct(void *, const void *, ptrdiff_t, bool, bool); -void glue_objc_setPropertyStruct(void *, const void *, ptrdiff_t, bool, bool); -void glue_objc_enumerationMutation(id); -int glue___gnu_objc_personality(int, int, uint64_t, void *, void *); -id glue_objc_retain(id); -id glue_objc_retainBlock(id); -id glue_objc_retainAutorelease(id); -void glue_objc_release(id); -id glue_objc_autorelease(id); -id glue_objc_autoreleaseReturnValue(id); -id glue_objc_retainAutoreleaseReturnValue(id); -id glue_objc_retainAutoreleasedReturnValue(id); -id glue_objc_storeStrong(id *, id); -id glue_objc_storeWeak(id *, id); -id glue_objc_loadWeakRetained(id *); -id glue_objc_initWeak(id *, id); -void glue_objc_destroyWeak(id *); -id glue_objc_loadWeak(id *); -void glue_objc_copyWeak(id *, id *); -void glue_objc_moveWeak(id *, id *); -SEL glue_sel_registerName(const char *); -const char *glue_sel_getName(SEL); -bool glue_sel_isEqual(SEL, SEL); -Class glue_objc_allocateClassPair(Class, const char *, size_t); -void glue_objc_registerClassPair(Class); -unsigned int glue_objc_getClassList(Class *, unsigned int); -Class *glue_objc_copyClassList(unsigned int *); -bool glue_class_isMetaClass(Class); -const char *glue_class_getName(Class); -Class glue_class_getSuperclass(Class); -unsigned long glue_class_getInstanceSize(Class); -bool glue_class_respondsToSelector(Class, SEL); -bool glue_class_conformsToProtocol(Class, Protocol *); -IMP glue_class_getMethodImplementation(Class, SEL); -IMP glue_class_getMethodImplementation_stret(Class, SEL); -Method glue_class_getInstanceMethod(Class, SEL); -bool glue_class_addMethod(Class, SEL, IMP, const char *); -IMP glue_class_replaceMethod(Class, SEL, IMP, const char *); -Class glue_object_getClass(id); -Class glue_object_setClass(id, Class); -const char *glue_object_getClassName(id); -const char *glue_protocol_getName(Protocol *); -bool glue_protocol_isEqual(Protocol *, Protocol *); -bool glue_protocol_conformsToProtocol(Protocol *, Protocol *); -objc_uncaught_exception_handler_t glue_objc_setUncaughtExceptionHandler(objc_uncaught_exception_handler_t); -void glue_objc_setForwardHandler(IMP, IMP); -void glue_objc_setEnumerationMutationHandler(objc_enumeration_mutation_handler_t); -id glue_objc_constructInstance(Class, void *); -void glue_objc_exit(void); -Ivar *glue_class_copyIvarList(Class, unsigned int *); -const char *glue_ivar_getName(Ivar); -const char *glue_ivar_getTypeEncoding(Ivar); -ptrdiff_t glue_ivar_getOffset(Ivar); -Method *glue_class_copyMethodList(Class, unsigned int *); -SEL glue_method_getName(Method); -const char *glue_method_getTypeEncoding(Method); -objc_property_t *glue_class_copyPropertyList(Class, unsigned int *); -const char *glue_property_getName(objc_property_t); -char *glue_property_copyAttributeValue(objc_property_t, const char *); -void *glue_objc_destructInstance(id); -void *glue_objc_autoreleasePoolPush(void); -void glue_objc_autoreleasePoolPop(void *); -id glue__objc_rootAutorelease(id); -/* The following functions are private! Don't use! */ -struct objc_hashtable *glue_objc_hashtable_new(objc_hashtable_hash_func, objc_hashtable_equal_func, uint32_t); -void glue_objc_hashtable_set(struct objc_hashtable *, const void *, const void *); -void *glue_objc_hashtable_get(struct objc_hashtable *, const void *); -void glue_objc_hashtable_delete(struct objc_hashtable *, const void *); -void glue_objc_hashtable_free(struct objc_hashtable *); -/* Public functions again */ -void glue_objc_setTaggedPointerSecret(uintptr_t); -int glue_objc_registerTaggedPointerClass(Class); -bool glue_object_isTaggedPointer(id); -uintptr_t glue_object_getTaggedPointerValue(id); -id glue_objc_createTaggedPointer(int, uintptr_t); DELETED src/runtime/morphos.fd Index: src/runtime/morphos.fd ================================================================== --- src/runtime/morphos.fd +++ src/runtime/morphos.fd @@ -1,96 +0,0 @@ -##base _ObjFWRTBase -##bias 30 -##public -* The following function is only for the linklib. -glue_objc_init(version,libc)(sysv,r12base) -glue___objc_exec_class(module)(sysv,r12base) -glue_objc_msg_lookup(object,selector)(sysv,r12base) -glue_objc_msg_lookup_stret(object,selector)(sysv,r12base) -glue_objc_msg_lookup_super(super,selector)(sysv,r12base) -glue_objc_msg_lookup_super_stret(super,selector)(sysv,r12base) -glue_objc_lookUpClass(name)(sysv,r12base) -glue_objc_getClass(name)(sysv,r12base) -glue_objc_getRequiredClass(name)(sysv,r12base) -glue_objc_lookup_class(name)(sysv,r12base) -glue_objc_get_class(name)(sysv,r12base) -glue_objc_exception_throw(object)(sysv,r12base) -glue_objc_sync_enter(object)(sysv,r12base) -glue_objc_sync_exit(object)(sysv,r12base) -glue_objc_getProperty(self,_cmd,offset,atomic)(sysv,r12base) -glue_objc_setProperty(self,_cmd,offset,value,atomic,copy)(sysv,r12base) -glue_objc_getPropertyStruct(dest,src,size,atomic,strong)(sysv,r12base) -glue_objc_setPropertyStruct(dest,src,size,atomic,strong)(sysv,r12base) -glue_objc_enumerationMutation(object)(sysv,r12base) -glue___gnu_objc_personality(version,actions,exClass,ex,ctx)(sysv,r12base) -glue_objc_retain(object)(sysv,r12base) -glue_objc_retainBlock(block)(sysv,r12base) -glue_objc_retainAutorelease(object)(sysv,r12base) -glue_objc_release(object)(sysv,r12base) -glue_objc_autorelease(object)(sysv,r12base) -glue_objc_autoreleaseReturnValue(object)(sysv,r12base) -glue_objc_retainAutoreleaseReturnValue(object)(sysv,r12base) -glue_objc_retainAutoreleasedReturnValue(object)(sysv,r12base) -glue_objc_storeStrong(object,value)(sysv,r12base) -glue_objc_storeWeak(object,value)(sysv,r12base) -glue_objc_loadWeakRetained(object)(sysv,r12base) -glue_objc_initWeak(object,value)(sysv,r12base) -glue_objc_destroyWeak(object)(sysv,r12base) -glue_objc_loadWeak(object)(sysv,r12base) -glue_objc_copyWeak(dest,src)(sysv,r12base) -glue_objc_moveWeak(dest,src)(sysv,r12base) -glue_sel_registerName(name)(sysv,r12base) -glue_sel_getName(selector)(sysv,r12base) -glue_sel_isEqual(selector1,selector2)(sysv,r12base) -glue_objc_allocateClassPair(superclass,name,extraBytes)(sysv,r12base) -glue_objc_registerClassPair(class_)(sysv,r12base) -glue_objc_getClassList(buffer,count)(sysv,r12base) -glue_objc_copyClassList(length)(sysv,r12base) -glue_class_isMetaClass(class_)(sysv,r12base) -glue_class_getName(class_)(sysv,r12base) -glue_class_getSuperclass(class_)(sysv,r12base) -glue_class_getInstanceSize(class_)(sysv,r12base) -glue_class_respondsToSelector(class_,selector)(sysv,r12base) -glue_class_conformsToProtocol(class_,p)(sysv,r12base) -glue_class_getMethodImplementation(class_,selector)(sysv,r12base) -glue_class_getMethodImplementation_stret(class_,selector)(sysv,r12base) -glue_class_getInstanceMethod(class_,selector)(sysv,r12base) -glue_class_addMethod(class_,selector,implementation,typeEncoding)(sysv,r12base) -glue_class_replaceMethod(class_,selector,implementation,typeEncoding)(sysv,r12base) -glue_object_getClass(object)(sysv,r12base) -glue_object_setClass(object,class_)(sysv,r12base) -glue_object_getClassName(object)(sysv,r12base) -glue_protocol_getName(protocol)(sysv,r12base) -glue_protocol_isEqual(protocol1,protocol2)(sysv,r12base) -glue_protocol_conformsToProtocol(protocol1,protocol2)(sysv,r12base) -glue_objc_setUncaughtExceptionHandler(handler)(sysv,r12base) -glue_objc_setForwardHandler(forward,stretForward)(sysv,r12base) -glue_objc_setEnumerationMutationHandler(handler)(sysv,r12base) -glue_objc_constructInstance(class_,bytes)(sysv,r12base) -glue_objc_exit()(sysv,r12base) -glue_class_copyIvarList(class_,outCount)(sysv,r12base) -glue_ivar_getName(ivar)(sysv,r12base) -glue_ivar_getTypeEncoding(ivar)(sysv,r12base) -glue_ivar_getOffset(ivar)(sysv,r12base) -glue_class_copyMethodList(class_,outCount)(sysv,r12base) -glue_method_getName(method)(sysv,r12base) -glue_method_getTypeEncoding(method)(sysv,r12base) -glue_class_copyPropertyList(class_,outCount)(sysv,r12base) -glue_property_getName(property)(sysv,r12base) -glue_property_copyAttributeValue(property,name)(sysv,r12base) -glue_objc_destructInstance(object)(sysv,r12base) -glue_objc_autoreleasePoolPush()(sysv,r12base) -glue_objc_autoreleasePoolPop(pool)(sysv,r12base) -glue__objc_rootAutorelease(object)(sysv,r12base) -* The following functions are private! Don't use! -glue_objc_hashtable_new(hash,equal,size)(sysv,r12base) -glue_objc_hashtable_set(table,key,object)(sysv,r12base) -glue_objc_hashtable_get(table,key)(sysv,r12base) -glue_objc_hashtable_delete(table,key)(sysv,r12base) -glue_objc_hashtable_free(table)(sysv,r12base) -* Public functions again -glue_objc_setTaggedPointerSecret(secret)(sysv,r12base) -glue_objc_registerTaggedPointerClass(class_)(sysv,r12base) -glue_object_isTaggedPointer(object)(sysv,r12base) -glue_object_getTaggedPointerValue(object)(sysv,r12base) -glue_objc_createTaggedPointer(class_,value)(sysv,r12base) -##end Index: src/runtime/private.h ================================================================== --- src/runtime/private.h +++ src/runtime/private.h @@ -38,11 +38,11 @@ unsigned long version; unsigned long info; long instanceSize; struct objc_ivar_list *_Nullable ivars; struct objc_method_list *_Nullable methodList; - struct objc_dtable *_Nonnull DTable; + struct objc_dtable *_Nonnull dTable; Class _Nullable *_Nullable subclassList; void *_Nullable siblingClass; struct objc_protocol_list *_Nullable protocols; void *_Nullable GCObjectType; unsigned long ABIVersion; @@ -199,11 +199,11 @@ struct objc_sparsearray { struct objc_sparsearray_data { void *_Nullable next[256]; } *_Nonnull data; - uint8_t indexSize; + uint8_t levels; }; struct objc_dtable { struct objc_dtable_level2 { #ifdef OF_SELUID24 @@ -279,35 +279,35 @@ # define __gnu_objc_personality(version, actions, exClass, ex, ctx) \ __gnu_objc_personality_v0(version, actions, *exClass, ex, ctx) # endif #endif -extern void objc_register_all_categories(struct objc_symtab *_Nonnull); +extern void objc_registerAllCategories(struct objc_symtab *_Nonnull); extern struct objc_category *_Nullable *_Nullable - objc_categories_for_class(Class _Nonnull); -extern void objc_unregister_all_categories(void); -extern void objc_initialize_class(Class _Nonnull); -extern void objc_update_dtable(Class _Nonnull); -extern void objc_register_all_classes(struct objc_symtab *_Nonnull); -extern Class _Nullable objc_classname_to_class(const char *_Nonnull, bool); -extern void objc_unregister_class(Class _Nonnull); -extern void objc_unregister_all_classes(void); -extern uint32_t objc_hash_string(const void *_Nonnull); -extern bool objc_equal_string(const void *_Nonnull, const void *_Nonnull); + objc_categoriesForClass(Class _Nonnull); +extern void objc_unregisterAllCategories(void); +extern void objc_initializeClass(Class _Nonnull); +extern void objc_updateDTable(Class _Nonnull); +extern void objc_registerAllClasses(struct objc_symtab *_Nonnull); +extern Class _Nullable objc_classnameToClass(const char *_Nonnull, bool); +extern void objc_unregisterClass(Class _Nonnull); +extern void objc_unregisterAllClasses(void); +extern uint32_t objc_string_hash(const void *_Nonnull); +extern bool objc_string_equal(const void *_Nonnull, const void *_Nonnull); extern struct objc_hashtable *_Nonnull objc_hashtable_new( objc_hashtable_hash_func, objc_hashtable_equal_func, uint32_t); -extern struct objc_hashtable_bucket objc_deleted_bucket; +extern struct objc_hashtable_bucket objc_deletedBucket; extern void objc_hashtable_set(struct objc_hashtable *_Nonnull, const void *_Nonnull, const void *_Nonnull); extern void *_Nullable objc_hashtable_get(struct objc_hashtable *_Nonnull, const void *_Nonnull); extern void objc_hashtable_delete(struct objc_hashtable *_Nonnull, const void *_Nonnull); extern void objc_hashtable_free(struct objc_hashtable *_Nonnull); -extern void objc_register_selector(struct objc_selector *_Nonnull); -extern void objc_register_all_selectors(struct objc_symtab *_Nonnull); -extern void objc_unregister_all_selectors(void); +extern void objc_registerSelector(struct objc_selector *_Nonnull); +extern void objc_registerAllSelectors(struct objc_symtab *_Nonnull); +extern void objc_unregisterAllSelectors(void); extern struct objc_sparsearray *_Nonnull objc_sparsearray_new(uint8_t); extern void *_Nullable objc_sparsearray_get(struct objc_sparsearray *_Nonnull, uintptr_t); extern void objc_sparsearray_set(struct objc_sparsearray *_Nonnull, uintptr_t, void *_Nullable); @@ -317,22 +317,22 @@ struct objc_dtable *_Nonnull); extern void objc_dtable_set(struct objc_dtable *_Nonnull, uint32_t, IMP _Nullable); extern void objc_dtable_free(struct objc_dtable *_Nonnull); extern void objc_dtable_cleanup(void); -extern void objc_init_static_instances(struct objc_symtab *_Nonnull); -extern void objc_forget_pending_static_instances(void); -extern void objc_zero_weak_references(id _Nonnull); +extern void objc_initStaticInstances(struct objc_symtab *_Nonnull); +extern void objc_forgetPendingStaticInstances(void); +extern void objc_zeroWeakReferences(id _Nonnull); extern Class _Nullable object_getTaggedPointerClass(id _Nonnull); #ifdef OF_HAVE_THREADS -extern void objc_global_mutex_lock(void); -extern void objc_global_mutex_unlock(void); -extern void objc_global_mutex_free(void); +extern void objc_globalMutex_lock(void); +extern void objc_globalMutex_unlock(void); +extern void objc_globalMutex_free(void); #else -# define objc_global_mutex_lock() -# define objc_global_mutex_unlock() -# define objc_global_mutex_free() +# define objc_globalMutex_lock() +# define objc_globalMutex_unlock() +# define objc_globalMutex_free() #endif extern char *_Nullable objc_strdup(const char *_Nonnull string); static inline IMP _Nullable objc_dtable_get(const struct objc_dtable *_Nonnull dtable, uint32_t idx) @@ -356,15 +356,20 @@ #define OBJC_ERROR(...) \ objc_error("ObjFWRT @ " __FILE__ ":" OF_STRINGIFY(__LINE__), \ __VA_ARGS__) #if defined(OF_ELF) -# if defined(OF_X86_64) || defined(OF_X86) || defined(OF_POWERPC) || \ +# if defined(OF_X86_64) || defined(OF_X86) || \ defined(OF_ARM64) || defined(OF_ARM) || \ defined(OF_MIPS64_N64) || defined(OF_MIPS) || \ defined(OF_SPARC64) || defined(OF_SPARC) # define OF_ASM_LOOKUP +# endif +# if defined(OF_POWERPC64) || defined(OF_POWERPC) +# if !defined(_CALL_ELF) || _CALL_ELF == 1 +# define OF_ASM_LOOKUP +# endif # endif #elif defined(OF_WINDOWS) # if defined(OF_X86_64) || defined(OF_X86) # define OF_ASM_LOOKUP # endif Index: src/runtime/property.m ================================================================== --- src/runtime/property.m +++ src/runtime/property.m @@ -20,37 +20,44 @@ #import "ObjFWRT.h" #import "private.h" #ifdef OF_HAVE_THREADS # import "OFPlainMutex.h" -# define NUM_SPINLOCKS 8 /* needs to be a power of 2 */ -# define SPINLOCK_HASH(p) ((unsigned)((uintptr_t)p >> 4) & (NUM_SPINLOCKS - 1)) -static OFSpinlock spinlocks[NUM_SPINLOCKS]; +# define numSpinlocks 8 /* needs to be a power of 2 */ +static OFSpinlock spinlocks[numSpinlocks]; + +static OF_INLINE size_t +spinlockSlot(const void *ptr) +{ + return ((size_t)((uintptr_t)ptr >> 4) & (numSpinlocks - 1)); +} #endif #ifdef OF_HAVE_THREADS OF_CONSTRUCTOR() { - for (size_t i = 0; i < NUM_SPINLOCKS; i++) + for (size_t i = 0; i < numSpinlocks; i++) if (OFSpinlockNew(&spinlocks[i]) != 0) - OBJC_ERROR("Failed to initialize spinlocks!"); + OBJC_ERROR("Failed to create spinlocks!"); } #endif id objc_getProperty(id self, SEL _cmd, ptrdiff_t offset, bool atomic) { if (atomic) { id *ptr = (id *)(void *)((char *)self + offset); #ifdef OF_HAVE_THREADS - unsigned hash = SPINLOCK_HASH(ptr); + size_t slot = spinlockSlot(ptr); - OFEnsure(OFSpinlockLock(&spinlocks[hash]) == 0); + if (OFSpinlockLock(&spinlocks[slot]) != 0) + OBJC_ERROR("Failed to lock spinlock!"); @try { return [[*ptr retain] autorelease]; } @finally { - OFEnsure(OFSpinlockUnlock(&spinlocks[hash]) == 0); + if (OFSpinlockUnlock(&spinlocks[slot]) != 0) + OBJC_ERROR("Failed to unlock spinlock!"); } #else return [[*ptr retain] autorelease]; #endif } @@ -63,13 +70,14 @@ signed char copy) { if (atomic) { id *ptr = (id *)(void *)((char *)self + offset); #ifdef OF_HAVE_THREADS - unsigned hash = SPINLOCK_HASH(ptr); + size_t slot = spinlockSlot(ptr); - OFEnsure(OFSpinlockLock(&spinlocks[hash]) == 0); + if (OFSpinlockLock(&spinlocks[slot]) != 0) + OBJC_ERROR("Failed to lock spinlock!"); @try { #endif id old = *ptr; switch (copy) { @@ -84,11 +92,12 @@ } [old release]; #ifdef OF_HAVE_THREADS } @finally { - OFEnsure(OFSpinlockUnlock(&spinlocks[hash]) == 0); + if (OFSpinlockUnlock(&spinlocks[slot]) != 0) + OBJC_ERROR("Failed to unlock spinlock!"); } #endif return; } @@ -115,17 +124,19 @@ objc_getPropertyStruct(void *dest, const void *src, ptrdiff_t size, bool atomic, bool strong) { if (atomic) { #ifdef OF_HAVE_THREADS - unsigned hash = SPINLOCK_HASH(src); + size_t slot = spinlockSlot(src); - OFEnsure(OFSpinlockLock(&spinlocks[hash]) == 0); + if (OFSpinlockLock(&spinlocks[slot]) != 0) + OBJC_ERROR("Failed to lock spinlock!"); #endif memcpy(dest, src, size); #ifdef OF_HAVE_THREADS - OFEnsure(OFSpinlockUnlock(&spinlocks[hash]) == 0); + if (OFSpinlockUnlock(&spinlocks[slot]) != 0) + OBJC_ERROR("Failed to unlock spinlock!"); #endif return; } @@ -136,17 +147,19 @@ objc_setPropertyStruct(void *dest, const void *src, ptrdiff_t size, bool atomic, bool strong) { if (atomic) { #ifdef OF_HAVE_THREADS - unsigned hash = SPINLOCK_HASH(src); + size_t slot = spinlockSlot(src); - OFEnsure(OFSpinlockLock(&spinlocks[hash]) == 0); + if (OFSpinlockLock(&spinlocks[slot]) != 0) + OBJC_ERROR("Failed to lock spinlock!"); #endif memcpy(dest, src, size); #ifdef OF_HAVE_THREADS - OFEnsure(OFSpinlockUnlock(&spinlocks[hash]) == 0); + if (OFSpinlockUnlock(&spinlocks[slot]) != 0) + OBJC_ERROR("Failed to unlock spinlock!"); #endif return; } @@ -165,11 +178,11 @@ *outCount = 0; return NULL; } - objc_global_mutex_lock(); + objc_globalMutex_lock(); count = 0; if (class->info & OBJC_CLASS_INFO_NEW_ABI) for (iter = class->propertyList; iter != NULL; iter = iter->next) @@ -177,11 +190,11 @@ if (count == 0) { if (outCount != NULL) *outCount = 0; - objc_global_mutex_unlock(); + objc_globalMutex_unlock(); return NULL; } properties = malloc((count + 1) * sizeof(objc_property_t)); if (properties == NULL) @@ -189,17 +202,20 @@ i = 0; for (iter = class->propertyList; iter != NULL; iter = iter->next) for (unsigned int j = 0; j < iter->count; j++) properties[i++] = &iter->properties[j]; - OFEnsure(i == count); + + if (i != count) + OBJC_ERROR("Fatal internal inconsistency!"); + properties[count] = NULL; if (outCount != NULL) *outCount = count; - objc_global_mutex_unlock(); + objc_globalMutex_unlock(); return properties; } const char * @@ -251,9 +267,9 @@ #undef BOOL_CASE } if (nullIsError && ret == NULL) OBJC_ERROR("Not enough memory to copy property attribute " - "value"); + "value!"); return ret; } Index: src/runtime/protocol.m ================================================================== --- src/runtime/protocol.m +++ src/runtime/protocol.m @@ -65,14 +65,14 @@ for (long i = 0; i < protocolList->count; i++) if (protocol_conformsToProtocol(protocolList->list[i], protocol)) return true; - objc_global_mutex_lock(); + objc_globalMutex_lock(); - if ((categories = objc_categories_for_class(class)) == NULL) { - objc_global_mutex_unlock(); + if ((categories = objc_categoriesForClass(class)) == NULL) { + objc_globalMutex_unlock(); return false; } for (long i = 0; categories[i] != NULL; i++) { for (struct objc_protocol_list *protocolList = @@ -79,16 +79,16 @@ categories[i]->protocols; protocolList != NULL; protocolList = protocolList->next) { for (long j = 0; j < protocolList->count; j++) { if (protocol_conformsToProtocol( protocolList->list[j], protocol)) { - objc_global_mutex_unlock(); + objc_globalMutex_unlock(); return true; } } } } - objc_global_mutex_unlock(); + objc_globalMutex_unlock(); return false; } Index: src/runtime/selector.m ================================================================== --- src/runtime/selector.m +++ src/runtime/selector.m @@ -23,43 +23,43 @@ #import "private.h" #import "macros.h" #ifdef OF_SELUID24 -# define SEL_MAX 0xFFFFFF -# define SEL_SIZE 3 +static const uint32_t maxSel = 0xFFFFFF; +static const uint8_t selLevels = 3; #else -# define SEL_MAX 0xFFFF -# define SEL_SIZE 2 +static const uint32_t maxSel = 0xFFFF; +static const uint8_t selLevels = 2; #endif static struct objc_hashtable *selectors = NULL; static uint32_t selectorsCount = 0; static struct objc_sparsearray *selectorNames = NULL; static void **freeList = NULL; static size_t freeListCount = 0; void -objc_register_selector(struct objc_selector *selector) +objc_registerSelector(struct objc_selector *selector) { SEL existingSelector; const char *name; - if (selectorsCount > SEL_MAX) + if (selectorsCount > maxSel) OBJC_ERROR("Out of selector slots!"); if (selectors == NULL) selectors = objc_hashtable_new( - objc_hash_string, objc_equal_string, 2); + objc_string_hash, objc_string_equal, 2); else if ((existingSelector = objc_hashtable_get(selectors, (const char *)selector->UID)) != NULL) { selector->UID = existingSelector->UID; return; } if (selectorNames == NULL) - selectorNames = objc_sparsearray_new(SEL_SIZE); + selectorNames = objc_sparsearray_new(selLevels); name = (const char *)selector->UID; selector->UID = selectorsCount++; objc_hashtable_set(selectors, name, selector); @@ -70,22 +70,20 @@ SEL sel_registerName(const char *name) { struct objc_selector *selector; - objc_global_mutex_lock(); + objc_globalMutex_lock(); if (selectors != NULL && (selector = objc_hashtable_get(selectors, name)) != NULL) { - objc_global_mutex_unlock(); + objc_globalMutex_unlock(); return (SEL)selector; } - if ((selector = malloc(sizeof(*selector))) == NULL) - OBJC_ERROR("Not enough memory to allocate selector!"); - - if ((selector->UID = (uintptr_t)objc_strdup(name)) == 0) + if ((selector = malloc(sizeof(*selector))) == NULL || + (selector->UID = (uintptr_t)objc_strdup(name)) == 0) OBJC_ERROR("Not enough memory to allocate selector!"); selector->typeEncoding = NULL; if ((freeList = realloc(freeList, @@ -93,36 +91,36 @@ OBJC_ERROR("Not enough memory to allocate selector!"); freeList[freeListCount++] = selector; freeList[freeListCount++] = (char *)selector->UID; - objc_register_selector(selector); + objc_registerSelector(selector); - objc_global_mutex_unlock(); + objc_globalMutex_unlock(); return (SEL)selector; } void -objc_register_all_selectors(struct objc_symtab *symtab) +objc_registerAllSelectors(struct objc_symtab *symtab) { struct objc_selector *selector; if (symtab->selectorRefs == NULL) return; for (selector = symtab->selectorRefs; selector->UID != 0; selector++) - objc_register_selector(selector); + objc_registerSelector(selector); } const char * sel_getName(SEL selector) { const char *ret; - objc_global_mutex_lock(); + objc_globalMutex_lock(); ret = objc_sparsearray_get(selectorNames, (uint32_t)selector->UID); - objc_global_mutex_unlock(); + objc_globalMutex_unlock(); return ret; } bool @@ -130,11 +128,11 @@ { return (selector1->UID == selector2->UID); } void -objc_unregister_all_selectors(void) +objc_unregisterAllSelectors(void) { objc_hashtable_free(selectors); objc_sparsearray_free(selectorNames); if (freeList != NULL) { Index: src/runtime/sparsearray.m ================================================================== --- src/runtime/sparsearray.m +++ src/runtime/sparsearray.m @@ -20,33 +20,31 @@ #import "ObjFWRT.h" #import "private.h" struct objc_sparsearray * -objc_sparsearray_new(uint8_t indexSize) +objc_sparsearray_new(uint8_t levels) { struct objc_sparsearray *sparsearray; - if ((sparsearray = calloc(1, sizeof(*sparsearray))) == NULL) + if ((sparsearray = calloc(1, sizeof(*sparsearray))) == NULL || + (sparsearray->data = calloc(1, sizeof(*sparsearray->data))) == NULL) OBJC_ERROR("Failed to allocate memory for sparse array!"); - if ((sparsearray->data = calloc(1, sizeof(*sparsearray->data))) == NULL) - OBJC_ERROR("Failed to allocate memory for sparse array!"); - - sparsearray->indexSize = indexSize; + sparsearray->levels = levels; return sparsearray; } void * objc_sparsearray_get(struct objc_sparsearray *sparsearray, uintptr_t idx) { struct objc_sparsearray_data *iter = sparsearray->data; - for (uint8_t i = 0; i < sparsearray->indexSize - 1; i++) { + for (uint8_t i = 0; i < sparsearray->levels - 1; i++) { uintptr_t j = - (idx >> ((sparsearray->indexSize - i - 1) * 8)) & 0xFF; + (idx >> ((sparsearray->levels - i - 1) * 8)) & 0xFF; if ((iter = iter->next[j]) == NULL) return NULL; } @@ -57,13 +55,13 @@ objc_sparsearray_set(struct objc_sparsearray *sparsearray, uintptr_t idx, void *value) { struct objc_sparsearray_data *iter = sparsearray->data; - for (uint8_t i = 0; i < sparsearray->indexSize - 1; i++) { + for (uint8_t i = 0; i < sparsearray->levels - 1; i++) { uintptr_t j = - (idx >> ((sparsearray->indexSize - i - 1) * 8)) & 0xFF; + (idx >> ((sparsearray->levels - i - 1) * 8)) & 0xFF; if (iter->next[j] == NULL) if ((iter->next[j] = calloc(1, sizeof(struct objc_sparsearray_data))) == NULL) OBJC_ERROR("Failed to allocate memory for " @@ -88,8 +86,8 @@ } void objc_sparsearray_free(struct objc_sparsearray *sparsearray) { - freeSparsearrayData(sparsearray->data, sparsearray->indexSize); + freeSparsearrayData(sparsearray->data, sparsearray->levels); free(sparsearray); } Index: src/runtime/static-instances.m ================================================================== --- src/runtime/static-instances.m +++ src/runtime/static-instances.m @@ -23,11 +23,11 @@ static struct objc_static_instances **staticInstancesList = NULL; static size_t staticInstancesCount = 0; void -objc_init_static_instances(struct objc_symtab *symtab) +objc_initStaticInstances(struct objc_symtab *symtab) { struct objc_static_instances **staticInstances; /* Check if the class for a static instance became available */ for (size_t i = 0; i < staticInstancesCount; i++) { @@ -93,11 +93,11 @@ } } } void -objc_forget_pending_static_instances() +objc_forgetPendingStaticInstances() { free(staticInstancesList); staticInstancesList = NULL; staticInstancesCount = 0; } Index: src/runtime/synchronized.m ================================================================== --- src/runtime/synchronized.m +++ src/runtime/synchronized.m @@ -22,15 +22,15 @@ #import "private.h" #ifdef OF_HAVE_THREADS # import "OFPlainMutex.h" -static struct lock { +static struct Lock { id object; int count; OFPlainRecursiveMutex rmutex; - struct lock *next; + struct Lock *next; } *locks = NULL; static OFPlainMutex mutex; OF_CONSTRUCTOR() @@ -45,11 +45,11 @@ { if (object == nil) return 0; #ifdef OF_HAVE_THREADS - struct lock *lock; + struct Lock *lock; if (OFPlainMutexLock(&mutex) != 0) OBJC_ERROR("Failed to lock mutex!"); /* Look if we already have a lock */ @@ -96,11 +96,11 @@ { if (object == nil) return 0; #ifdef OF_HAVE_THREADS - struct lock *lock, *last = NULL; + struct Lock *lock, *last = NULL; if (OFPlainMutexLock(&mutex) != 0) OBJC_ERROR("Failed to lock mutex!"); for (lock = locks; lock != NULL; lock = lock->next) { @@ -128,10 +128,10 @@ OBJC_ERROR("Failed to unlock mutex!"); return 0; } - OBJC_ERROR("objc_sync_exit() was called for an object not locked!"); + OBJC_ERROR("objc_sync_exit() was called for an unlocked object!"); #else return 0; #endif } Index: src/runtime/tagged-pointer.m ================================================================== --- src/runtime/tagged-pointer.m +++ src/runtime/tagged-pointer.m @@ -15,39 +15,39 @@ #import "ObjFWRT.h" #import "private.h" -#define TAGGED_POINTER_BITS 4 -#define NUM_TAGGED_POINTER_CLASSES (1 << (TAGGED_POINTER_BITS - 1)) +#define numTaggedPointerBits 4 +#define maxNumTaggedPointerClasses (1 << (numTaggedPointerBits - 1)) -Class objc_tagged_pointer_classes[NUM_TAGGED_POINTER_CLASSES]; +Class objc_taggedPointerClasses[maxNumTaggedPointerClasses]; static int taggedPointerClassesCount; -uintptr_t objc_tagged_pointer_secret; +uintptr_t objc_taggedPointerSecret; void objc_setTaggedPointerSecret(uintptr_t secret) { - objc_tagged_pointer_secret = secret & ~(uintptr_t)1; + objc_taggedPointerSecret = secret & ~(uintptr_t)1; } int objc_registerTaggedPointerClass(Class class) { int i; - objc_global_mutex_lock(); + objc_globalMutex_lock(); - if (taggedPointerClassesCount == NUM_TAGGED_POINTER_CLASSES) { - objc_global_mutex_unlock(); + if (taggedPointerClassesCount == maxNumTaggedPointerClasses) { + objc_globalMutex_unlock(); return -1; } i = taggedPointerClassesCount++; - objc_tagged_pointer_classes[i] = class; + objc_taggedPointerClasses[i] = class; - objc_global_mutex_unlock(); + objc_globalMutex_unlock(); return i; } bool @@ -59,42 +59,42 @@ } Class object_getTaggedPointerClass(id object) { - uintptr_t pointer = (uintptr_t)object ^ objc_tagged_pointer_secret; + uintptr_t pointer = (uintptr_t)object ^ objc_taggedPointerSecret; - pointer &= (1 << TAGGED_POINTER_BITS) - 1; + pointer &= (1 << numTaggedPointerBits) - 1; pointer >>= 1; - if (pointer >= NUM_TAGGED_POINTER_CLASSES) + if (pointer >= maxNumTaggedPointerClasses) return Nil; - return objc_tagged_pointer_classes[pointer]; + return objc_taggedPointerClasses[pointer]; } uintptr_t object_getTaggedPointerValue(id object) { - uintptr_t pointer = (uintptr_t)object ^ objc_tagged_pointer_secret; + uintptr_t pointer = (uintptr_t)object ^ objc_taggedPointerSecret; - pointer >>= TAGGED_POINTER_BITS; + pointer >>= numTaggedPointerBits; return pointer; } id objc_createTaggedPointer(int class, uintptr_t value) { uintptr_t pointer; - if (class < 0 || class >= NUM_TAGGED_POINTER_CLASSES) + if (class < 0 || class >= maxNumTaggedPointerClasses) return nil; - if (value > (UINTPTR_MAX >> TAGGED_POINTER_BITS)) + if (value > (UINTPTR_MAX >> numTaggedPointerBits)) return nil; pointer = (class << 1) | 1; - pointer |= (value << TAGGED_POINTER_BITS); + pointer |= (value << numTaggedPointerBits); - return (id)(pointer ^ objc_tagged_pointer_secret); + return (id)(pointer ^ objc_taggedPointerSecret); } Index: src/runtime/threading.m ================================================================== --- src/runtime/threading.m +++ src/runtime/threading.m @@ -32,20 +32,20 @@ if (OFPlainRecursiveMutexNew(&globalMutex) != 0) OBJC_ERROR("Failed to create global mutex!"); } void -objc_global_mutex_lock(void) +objc_globalMutex_lock(void) { static OFOnceControl onceControl = OFOnceControlInitValue; OFOnce(&onceControl, init); if (OFPlainRecursiveMutexLock(&globalMutex) != 0) OBJC_ERROR("Failed to lock global mutex!"); } void -objc_global_mutex_unlock(void) +objc_globalMutex_unlock(void) { if (OFPlainRecursiveMutexUnlock(&globalMutex) != 0) OBJC_ERROR("Failed to unlock global mutex!"); } Index: tests/ForwardingTests.m ================================================================== --- tests/ForwardingTests.m +++ tests/ForwardingTests.m @@ -17,22 +17,22 @@ #include #import "TestsAppDelegate.h" -#define FMT @"%@ %@ %@ %@ %@ %@ %@ %@ %@ %g %g %g %g %g %g %g %g %g" +#define FORMAT @"%@ %@ %@ %@ %@ %@ %@ %@ %@ %g %g %g %g %g %g %g %g %g" #define ARGS @"a", @"b", @"c", @"d", @"e", @"f", @"g", @"h", @"i", \ 1.5, 2.25, 3.125, 4.0625, 5.03125, 6.5, 7.25, 8.0, 9.0 #define RESULT @"a b c d e f g h i 1.5 2.25 3.125 4.0625 5.03125 6.5 7.25 8 9" -static OFString *module = @"Forwarding"; -static size_t forwardings = 0; +static OFString *const module = @"Forwarding"; +static size_t forwardingsCount = 0; static bool success = false; static id target = nil; -struct stret_test { - char s[1024]; +struct StretTest { + char buffer[1024]; }; @interface ForwardingTest: OFObject @end @@ -41,17 +41,17 @@ - (void)test; - (uint32_t)forwardingTargetTest: (intptr_t)a0 : (intptr_t)a1 : (double)a2 : (double)a3; -- (OFString *)forwardingTargetVarArgTest: (OFConstantString *)fmt, ...; +- (OFString *)forwardingTargetVarArgTest: (OFConstantString *)format, ...; - (long double)forwardingTargetFPRetTest; -- (struct stret_test)forwardingTargetStRetTest; +- (struct StretTest)forwardingTargetStRetTest; - (void)forwardingTargetNilTest; - (void)forwardingTargetSelfTest; -- (struct stret_test)forwardingTargetNilStRetTest; -- (struct stret_test)forwardingTargetSelfStRetTest; +- (struct StretTest)forwardingTargetNilStRetTest; +- (struct StretTest)forwardingTargetSelfStRetTest; @end @interface ForwardingTarget: OFObject @end @@ -62,11 +62,11 @@ } @implementation ForwardingTest + (bool)resolveClassMethod: (SEL)selector { - forwardings++; + forwardingsCount++; if (sel_isEqual(selector, @selector(test))) { class_replaceMethod(object_getClass(self), @selector(test), (IMP)test, "v#:"); return YES; @@ -75,11 +75,11 @@ return NO; } + (bool)resolveInstanceMethod: (SEL)selector { - forwardings++; + forwardingsCount++; if (sel_isEqual(selector, @selector(test))) { class_replaceMethod(self, @selector(test), (IMP)test, "v@:"); return YES; } @@ -139,19 +139,19 @@ return 0; return 0x12345678; } -- (OFString *)forwardingTargetVarArgTest: (OFConstantString *)fmt, ... +- (OFString *)forwardingTargetVarArgTest: (OFConstantString *)format, ... { va_list args; OFString *ret; OFEnsure(self == target); - va_start(args, fmt); - ret = [[[OFString alloc] initWithFormat: fmt + va_start(args, format); + ret = [[[OFString alloc] initWithFormat: format arguments: args] autorelease]; va_end(args); return ret; } @@ -161,17 +161,17 @@ OFEnsure(self == target); return 12345678.00006103515625; } -- (struct stret_test)forwardingTargetStRetTest +- (struct StretTest)forwardingTargetStRetTest { - struct stret_test ret = { { 0 } }; + struct StretTest ret = { { 0 } }; OFEnsure(self == target); - memcpy(ret.s, "abcdefghijklmnopqrstuvwxyz", 27); + memcpy(ret.buffer, "abcdefghijklmnopqrstuvwxyz", 27); return ret; } @end @@ -180,55 +180,58 @@ { void *pool = objc_autoreleasePoolPush(); TEST(@"Forwarding a message and adding a class method", R([ForwardingTest test]) && success && - R([ForwardingTest test]) && forwardings == 1); + R([ForwardingTest test]) && forwardingsCount == 1); - ForwardingTest *t = [[[ForwardingTest alloc] init] autorelease]; + ForwardingTest *testObject = + [[[ForwardingTest alloc] init] autorelease]; success = false; - forwardings = 0; + forwardingsCount = 0; TEST(@"Forwarding a message and adding an instance method", - R([t test]) && success && R([t test]) && forwardings == 1); + R([testObject test]) && success && R([testObject test]) && + forwardingsCount == 1); #ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR target = [[[ForwardingTarget alloc] init] autorelease]; TEST(@"-[forwardingTargetForSelector:]", - [t forwardingTargetTest: 0xDEADBEEF - : -1 - : 1.25 - : 2.75] == 0x12345678) + [testObject forwardingTargetTest: 0xDEADBEEF + : -1 + : 1.25 + : 2.75] == 0x12345678) TEST(@"-[forwardingTargetForSelector:] variable arguments", - [[t forwardingTargetVarArgTest: FMT, ARGS] isEqual: RESULT]) + [[testObject forwardingTargetVarArgTest: FORMAT, ARGS] + isEqual: RESULT]) /* * Don't try fpret on Win64 if we don't have stret forwarding, as * long double is handled as a struct there. */ # if !defined(OF_WINDOWS) || !defined(OF_X86_64) || \ defined(OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET) TEST(@"-[forwardingTargetForSelector:] fp return", - [t forwardingTargetFPRetTest] == 12345678.00006103515625) + [testObject forwardingTargetFPRetTest] == 12345678.00006103515625) # endif # ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET TEST(@"-[forwardingTargetForSelector:] struct return", - !memcmp([t forwardingTargetStRetTest].s, + !memcmp([testObject forwardingTargetStRetTest].buffer, "abcdefghijklmnopqrstuvwxyz", 27)) # endif EXPECT_EXCEPTION(@"-[forwardingTargetForSelector:] nil target", - OFNotImplementedException, [t forwardingTargetNilTest]) + OFNotImplementedException, [testObject forwardingTargetNilTest]) EXPECT_EXCEPTION(@"-[forwardingTargetForSelector:] self target", - OFNotImplementedException, [t forwardingTargetSelfTest]) + OFNotImplementedException, [testObject forwardingTargetSelfTest]) # ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET EXPECT_EXCEPTION(@"-[forwardingTargetForSelector:] nil target + " @"stret", OFNotImplementedException, - [t forwardingTargetNilStRetTest]) + [testObject forwardingTargetNilStRetTest]) EXPECT_EXCEPTION(@"-[forwardingTargetForSelector:] self target + " @"stret", OFNotImplementedException, - [t forwardingTargetSelfStRetTest]) + [testObject forwardingTargetSelfStRetTest]) # endif #endif objc_autoreleasePoolPop(pool); } @end Index: tests/Makefile ================================================================== --- tests/Makefile +++ tests/Makefile @@ -22,24 +22,24 @@ OFListTests.m \ OFLocaleTests.m \ OFMethodSignatureTests.m \ OFNumberTests.m \ OFObjectTests.m \ + OFPBKDF2Tests.m \ OFPropertyListTests.m \ + OFScryptTests.m \ OFSetTests.m \ OFStreamTests.m \ OFStringTests.m \ OFSystemInfoTests.m \ OFURLTests.m \ OFValueTests.m \ OFXMLElementBuilderTests.m \ OFXMLNodeTests.m \ OFXMLParserTests.m \ - PBKDF2Tests.m \ RuntimeTests.m \ ${RUNTIME_ARC_TESTS_M} \ - ScryptTests.m \ TestsAppDelegate.m \ ${USE_SRCS_FILES} \ ${USE_SRCS_PLUGINS} \ ${USE_SRCS_SOCKETS} \ ${USE_SRCS_THREADS} \ @@ -61,13 +61,13 @@ SRCS_SOCKETS = OFDNSResolverTests.m \ ${OF_HTTP_CLIENT_TESTS_M} \ OFHTTPCookieTests.m \ OFHTTPCookieManagerTests.m \ OFKernelEventObserverTests.m \ + OFSocketTests.m \ OFTCPSocketTests.m \ OFUDPSocketTests.m \ - SocketTests.m \ ${USE_SRCS_IPX} SRCS_THREADS = OFThreadTests.m SRCS_WINDOWS = OFWindowsRegistryKeyTests.m IOS_USER ?= mobile @@ -79,25 +79,27 @@ .PHONY: run run-on-ios run-on-android run: rm -f libobjfw.so.${OBJFW_LIB_MAJOR} rm -f libobjfw.so.${OBJFW_LIB_MAJOR_MINOR} - rm -f objfw.dll libobjfw.${OBJFW_LIB_MAJOR}.dylib + rm -f objfw${OBJFW_LIB_MAJOR}.dll libobjfw.${OBJFW_LIB_MAJOR}.dylib rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR} rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR} - rm -f objfwrt.dll libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib + rm -f objfwrt${OBJFWRT_LIB_MAJOR}.dll + rm -f libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib rm -f ${OBJFWRT_AMIGA_LIB} if test -f ../src/libobjfw.so; then \ ${LN_S} ../src/libobjfw.so libobjfw.so.${OBJFW_LIB_MAJOR}; \ ${LN_S} ../src/libobjfw.so \ libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; \ elif test -f ../src/libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; then \ ${LN_S} ../src/libobjfw.so.${OBJFW_LIB_MAJOR_MINOR} \ libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; \ fi - if test -f ../src/objfw.dll; then \ - ${LN_S} ../src/objfw.dll objfw.dll; \ + if test -f ../src/objfw${OBJFW_LIB_MAJOR}.dll; then \ + ${LN_S} ../src/objfw${OBJFW_LIB_MAJOR}.dll \ + objfw${OBJFW_LIB_MAJOR}.dll; \ fi if test -f ../src/libobjfw.dylib; then \ ${LN_S} ../src/libobjfw.dylib \ libobjfw.${OBJFW_LIB_MAJOR}.dylib; \ fi @@ -107,12 +109,13 @@ ${LN_S} ../src/runtime/libobjfwrt.so \ libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; \ elif test -f ../src/runtime/libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; then \ ${LN_S} ../src/runtime/libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR} libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; \ fi - if test -f ../src/runtime/objfwrt.dll; then \ - ${LN_S} ../src/runtime/objfwrt.dll objfwrt.dll; \ + if test -f ../src/runtime/objfwrt${OBJFWRT_LIB_MAJOR}.dll; then \ + ${LN_S} ../src/runtime/objfwrt${OBJFWRT_LIB_MAJOR}.dll \ + objfwrt${OBJFWRT_LIB_MAJOR}.dll; \ fi if test -f ../src/runtime/libobjfwrt.dylib; then \ ${LN_S} ../src/runtime/libobjfwrt.dylib \ libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib; \ fi @@ -125,14 +128,16 @@ DYLD_LIBRARY_PATH=.$${DYLD_LIBRARY_PATH+:}$$DYLD_LIBRARY_PATH \ LIBRARY_PATH=.$${LIBRARY_PATH+:}$$LIBRARY_PATH \ ASAN_OPTIONS=allocator_may_return_null=1 \ ${WRAPPER} ./${PROG_NOINST}; EXIT=$$?; \ rm -f libobjfw.so.${OBJFW_LIB_MAJOR}; \ - rm -f libobjfw.so.${OBJFW_LIB_MAJOR_MINOR} objfw.dll; \ + rm -f libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; \ + rm -f objfw${OBJFW_LIB_MAJOR}.dll; \ rm -f libobjfw.${OBJFW_LIB_MAJOR}.dylib; \ rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR}; \ - rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR} objfwrt.dll; \ + rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; \ + rm -f objfwrt${OBJFWRT_LIB_MAJOR}.dll; \ rm -f libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib; \ exit $$EXIT run-on-ios: all if [ -z "${IOS_HOST}" ]; then \ Index: tests/OFArrayTests.m ================================================================== --- tests/OFArrayTests.m +++ tests/OFArrayTests.m @@ -15,12 +15,12 @@ #include "config.h" #import "TestsAppDelegate.h" -static OFString *module = nil; -static OFString *c_ary[] = { +static OFString *module; +static OFString *const cArray[] = { @"Foo", @"Bar", @"Baz" }; @@ -125,283 +125,300 @@ @implementation TestsAppDelegate (OFArrayTests) - (void)arrayTestsWithClass: (Class)arrayClass mutableClass: (Class)mutableArrayClass { void *pool = objc_autoreleasePoolPush(); - OFArray *a[3]; - OFMutableArray *m[2]; + OFArray *array1, *array2; + OFMutableArray *mutableArray1, *mutableArray2; OFEnumerator *enumerator; - id obj; + id object; bool ok; size_t i; - TEST(@"+[array]", (m[0] = [mutableArrayClass array])) + TEST(@"+[array]", (mutableArray1 = [mutableArrayClass array])) TEST(@"+[arrayWithObjects:]", - (a[0] = [arrayClass arrayWithObjects: @"Foo", @"Bar", @"Baz", nil])) + (array1 = + [arrayClass arrayWithObjects: @"Foo", @"Bar", @"Baz", nil])) TEST(@"+[arrayWithObjects:count:]", - (a[1] = [arrayClass arrayWithObjects: c_ary count: 3]) && - [a[1] isEqual: a[0]]) + (array2 = [arrayClass arrayWithObjects: cArray count: 3]) && + [array2 isEqual: array1]) TEST(@"-[description]", - [a[0].description isEqual: @"(\n\tFoo,\n\tBar,\n\tBaz\n)"]) + [array1.description isEqual: @"(\n\tFoo,\n\tBar,\n\tBaz\n)"]) - TEST(@"-[addObject:]", R([m[0] addObject: c_ary[0]]) && - R([m[0] addObject: c_ary[2]])) + TEST(@"-[addObject:]", + R([mutableArray1 addObject: cArray[0]]) && + R([mutableArray1 addObject: cArray[2]])) TEST(@"-[insertObject:atIndex:]", - R([m[0] insertObject: c_ary[1] atIndex: 1])) + R([mutableArray1 insertObject: cArray[1] atIndex: 1])) - TEST(@"-[count]", m[0].count == 3 && a[0].count == 3 && a[1].count == 3) + TEST(@"-[count]", + mutableArray1.count == 3 && array1.count == 3 && array2.count == 3) - TEST(@"-[isEqual:]", [m[0] isEqual: a[0]] && [a[0] isEqual: a[1]]) + TEST(@"-[isEqual:]", + [mutableArray1 isEqual: array1] && [array1 isEqual: array2]) TEST(@"-[objectAtIndex:]", - [[m[0] objectAtIndex: 0] isEqual: c_ary[0]] && - [[m[0] objectAtIndex: 1] isEqual: c_ary[1]] && - [[m[0] objectAtIndex: 2] isEqual: c_ary[2]] && - [[a[0] objectAtIndex: 0] isEqual: c_ary[0]] && - [[a[0] objectAtIndex: 1] isEqual: c_ary[1]] && - [[a[0] objectAtIndex: 2] isEqual: c_ary[2]] && - [[a[1] objectAtIndex: 0] isEqual: c_ary[0]] && - [[a[1] objectAtIndex: 1] isEqual: c_ary[1]] && - [[a[1] objectAtIndex: 2] isEqual: c_ary[2]]) + [[mutableArray1 objectAtIndex: 0] isEqual: cArray[0]] && + [[mutableArray1 objectAtIndex: 1] isEqual: cArray[1]] && + [[mutableArray1 objectAtIndex: 2] isEqual: cArray[2]] && + [[array1 objectAtIndex: 0] isEqual: cArray[0]] && + [[array1 objectAtIndex: 1] isEqual: cArray[1]] && + [[array1 objectAtIndex: 2] isEqual: cArray[2]] && + [[array2 objectAtIndex: 0] isEqual: cArray[0]] && + [[array2 objectAtIndex: 1] isEqual: cArray[1]] && + [[array2 objectAtIndex: 2] isEqual: cArray[2]]) TEST(@"-[containsObject:]", - [a[0] containsObject: c_ary[1]] && - ![a[0] containsObject: @"nonexistent"]) + [array1 containsObject: cArray[1]] && + ![array1 containsObject: @"nonexistent"]) TEST(@"-[containsObjectIdenticalTo:]", - [a[0] containsObjectIdenticalTo: c_ary[1]] && - ![a[0] containsObjectIdenticalTo: - [OFString stringWithString: c_ary[1]]]) + [array1 containsObjectIdenticalTo: cArray[1]] && + ![array1 containsObjectIdenticalTo: + [OFString stringWithString: cArray[1]]]) - TEST(@"-[indexOfObject:]", [a[0] indexOfObject: c_ary[1]] == 1) + TEST(@"-[indexOfObject:]", [array1 indexOfObject: cArray[1]] == 1) TEST(@"-[indexOfObjectIdenticalTo:]", - [a[1] indexOfObjectIdenticalTo: c_ary[1]] == 1) + [array2 indexOfObjectIdenticalTo: cArray[1]] == 1) TEST(@"-[objectsInRange:]", - [[a[0] objectsInRange: OFRangeMake(1, 2)] isEqual: - [arrayClass arrayWithObjects: c_ary[1], c_ary[2], nil]]) + [[array1 objectsInRange: OFRangeMake(1, 2)] isEqual: + [arrayClass arrayWithObjects: cArray[1], cArray[2], nil]]) TEST(@"-[replaceObject:withObject:]", - R([m[0] replaceObject: c_ary[1] withObject: c_ary[0]]) && - [[m[0] objectAtIndex: 0] isEqual: c_ary[0]] && - [[m[0] objectAtIndex: 1] isEqual: c_ary[0]] && - [[m[0] objectAtIndex: 2] isEqual: c_ary[2]]) + R([mutableArray1 replaceObject: cArray[1] withObject: cArray[0]]) && + [[mutableArray1 objectAtIndex: 0] isEqual: cArray[0]] && + [[mutableArray1 objectAtIndex: 1] isEqual: cArray[0]] && + [[mutableArray1 objectAtIndex: 2] isEqual: cArray[2]]) TEST(@"-[replaceObject:identicalTo:]", - R([m[0] replaceObjectIdenticalTo: c_ary[0] withObject: c_ary[1]]) && - [[m[0] objectAtIndex: 0] isEqual: c_ary[1]] && - [[m[0] objectAtIndex: 1] isEqual: c_ary[0]] && - [[m[0] objectAtIndex: 2] isEqual: c_ary[2]]) + R([mutableArray1 replaceObjectIdenticalTo: cArray[0] + withObject: cArray[1]]) && + [[mutableArray1 objectAtIndex: 0] isEqual: cArray[1]] && + [[mutableArray1 objectAtIndex: 1] isEqual: cArray[0]] && + [[mutableArray1 objectAtIndex: 2] isEqual: cArray[2]]) TEST(@"-[replaceObjectAtIndex:withObject:]", - R([m[0] replaceObjectAtIndex: 0 withObject: c_ary[0]]) && - [[m[0] objectAtIndex: 0] isEqual: c_ary[0]] && - [[m[0] objectAtIndex: 1] isEqual: c_ary[0]] && - [[m[0] objectAtIndex: 2] isEqual: c_ary[2]]) + R([mutableArray1 replaceObjectAtIndex: 0 withObject: cArray[0]]) && + [[mutableArray1 objectAtIndex: 0] isEqual: cArray[0]] && + [[mutableArray1 objectAtIndex: 1] isEqual: cArray[0]] && + [[mutableArray1 objectAtIndex: 2] isEqual: cArray[2]]) TEST(@"-[removeObject:]", - R([m[0] removeObject: c_ary[0]]) && m[0].count == 2) + R([mutableArray1 removeObject: cArray[0]]) && + mutableArray1.count == 2) TEST(@"-[removeObjectIdenticalTo:]", - R([m[0] removeObjectIdenticalTo: c_ary[2]]) && m[0].count == 1) - - m[1] = [[a[0] mutableCopy] autorelease]; - TEST(@"-[removeObjectAtIndex:]", R([m[1] removeObjectAtIndex: 1]) && - m[1].count == 2 && [[m[1] objectAtIndex: 1] isEqual: c_ary[2]]) - - m[1] = [[a[0] mutableCopy] autorelease]; - TEST(@"-[removeObjectsInRange:]", - R([m[1] removeObjectsInRange: OFRangeMake(0, 2)]) && - m[1].count == 1 && [[m[1] objectAtIndex: 0] isEqual: c_ary[2]]) - - m[1] = [[a[0] mutableCopy] autorelease]; - [m[1] addObject: @"qux"]; - [m[1] addObject: @"last"]; - TEST(@"-[reverse]", - R([m[1] reverse]) && [m[1] isEqual: [arrayClass arrayWithObjects: - @"last", @"qux", @"Baz", @"Bar", @"Foo", nil]]) - - m[1] = [[a[0] mutableCopy] autorelease]; - [m[1] addObject: @"qux"]; - [m[1] addObject: @"last"]; - TEST(@"-[reversedArray]", - [[m[1] reversedArray] isEqual: [arrayClass arrayWithObjects: - @"last", @"qux", @"Baz", @"Bar", @"Foo", nil]]) - - m[1] = [[a[0] mutableCopy] autorelease]; - [m[1] addObject: @"0"]; - [m[1] addObject: @"z"]; - TEST(@"-[sortedArray]", - [[m[1] sortedArray] isEqual: [arrayClass arrayWithObjects: - @"0", @"Bar", @"Baz", @"Foo", @"z", nil]] && - [[m[1] sortedArrayUsingSelector: @selector(compare:) - options: OFArraySortDescending] + R([mutableArray1 removeObjectIdenticalTo: cArray[2]]) && + mutableArray1.count == 1) + + mutableArray2 = [[array1 mutableCopy] autorelease]; + TEST(@"-[removeObjectAtIndex:]", + R([mutableArray2 removeObjectAtIndex: 1]) && + mutableArray2.count == 2 && + [[mutableArray2 objectAtIndex: 1] isEqual: cArray[2]]) + + mutableArray2 = [[array1 mutableCopy] autorelease]; + TEST(@"-[removeObjectsInRange:]", + R([mutableArray2 removeObjectsInRange: OFRangeMake(0, 2)]) && + mutableArray2.count == 1 && + [[mutableArray2 objectAtIndex: 0] isEqual: cArray[2]]) + + mutableArray2 = [[array1 mutableCopy] autorelease]; + [mutableArray2 addObject: @"qux"]; + [mutableArray2 addObject: @"last"]; + TEST(@"-[reverse]", + R([mutableArray2 reverse]) && + [mutableArray2 isEqual: [arrayClass arrayWithObjects: + @"last", @"qux", @"Baz", @"Bar", @"Foo", nil]]) + + mutableArray2 = [[array1 mutableCopy] autorelease]; + [mutableArray2 addObject: @"qux"]; + [mutableArray2 addObject: @"last"]; + TEST(@"-[reversedArray]", + [[mutableArray2 reversedArray] isEqual: + [arrayClass arrayWithObjects: + @"last", @"qux", @"Baz", @"Bar", @"Foo", nil]]) + + mutableArray2 = [[array1 mutableCopy] autorelease]; + [mutableArray2 addObject: @"0"]; + [mutableArray2 addObject: @"z"]; + TEST(@"-[sortedArray]", + [[mutableArray2 sortedArray] isEqual: [arrayClass arrayWithObjects: + @"0", @"Bar", @"Baz", @"Foo", @"z", nil]] && + [[mutableArray2 sortedArrayUsingSelector: @selector(compare:) + options: OFArraySortDescending] isEqual: [arrayClass arrayWithObjects: @"z", @"Foo", @"Baz", @"Bar", @"0", nil]]) EXPECT_EXCEPTION(@"Detect out of range in -[objectAtIndex:]", - OFOutOfRangeException, [a[0] objectAtIndex: a[0].count]) + OFOutOfRangeException, [array1 objectAtIndex: array1.count]) EXPECT_EXCEPTION(@"Detect out of range in -[removeObjectsInRange:]", - OFOutOfRangeException, [m[0] removeObjectsInRange: - OFRangeMake(0, m[0].count + 1)]) + OFOutOfRangeException, [mutableArray1 removeObjectsInRange: + OFRangeMake(0, mutableArray1.count + 1)]) TEST(@"-[componentsJoinedByString:]", - (a[1] = [arrayClass arrayWithObjects: @"", @"a", @"b", @"c", + (array2 = [arrayClass arrayWithObjects: @"", @"a", @"b", @"c", nil]) && - [[a[1] componentsJoinedByString: @" "] isEqual: @" a b c"] && - (a[1] = [arrayClass arrayWithObject: @"foo"]) && - [[a[1] componentsJoinedByString: @" "] isEqual: @"foo"]) + [[array2 componentsJoinedByString: @" "] isEqual: @" a b c"] && + (array2 = [arrayClass arrayWithObject: @"foo"]) && + [[array2 componentsJoinedByString: @" "] isEqual: @"foo"]) TEST(@"-[componentsJoinedByString:options]", - (a[1] = [arrayClass arrayWithObjects: @"", @"foo", @"", @"", @"bar", - @"", nil]) && - [[a[1] componentsJoinedByString: @" " - options: OFArraySkipEmptyComponents] + (array2 = [arrayClass arrayWithObjects: @"", @"foo", @"", @"", + @"bar", @"", nil]) && + [[array2 componentsJoinedByString: @" " + options: OFArraySkipEmptyComponents] isEqual: @"foo bar"]) - m[0] = [[a[0] mutableCopy] autorelease]; + mutableArray1 = [[array1 mutableCopy] autorelease]; ok = true; i = 0; - TEST(@"-[objectEnumerator]", (enumerator = [m[0] objectEnumerator])) + TEST(@"-[objectEnumerator]", + (enumerator = [mutableArray1 objectEnumerator])) - while ((obj = [enumerator nextObject]) != nil) { - if (![obj isEqual: c_ary[i]]) + while ((object = [enumerator nextObject]) != nil) { + if (![object isEqual: cArray[i]]) ok = false; - [m[0] replaceObjectAtIndex: i withObject: @""]; + [mutableArray1 replaceObjectAtIndex: i withObject: @""]; i++; } - if (m[0].count != i) + if (mutableArray1.count != i) ok = false; TEST(@"OFEnumerator's -[nextObject]", ok) - [m[0] removeObjectAtIndex: 0]; + [mutableArray1 removeObjectAtIndex: 0]; EXPECT_EXCEPTION(@"Detection of mutation during enumeration", OFEnumerationMutationException, [enumerator nextObject]) - m[0] = [[a[0] mutableCopy] autorelease]; + mutableArray1 = [[array1 mutableCopy] autorelease]; ok = true; i = 0; - for (OFString *s in m[0]) { - if (![s isEqual: c_ary[i]]) + for (OFString *string in mutableArray1) { + if (![string isEqual: cArray[i]]) ok = false; - [m[0] replaceObjectAtIndex: i withObject: @""]; + [mutableArray1 replaceObjectAtIndex: i withObject: @""]; i++; } - if (m[0].count != i) + if (mutableArray1.count != i) ok = false; TEST(@"Fast Enumeration", ok) - [m[0] replaceObjectAtIndex: 0 withObject: c_ary[0]]; - [m[0] replaceObjectAtIndex: 1 withObject: c_ary[1]]; - [m[0] replaceObjectAtIndex: 2 withObject: c_ary[2]]; + [mutableArray1 replaceObjectAtIndex: 0 withObject: cArray[0]]; + [mutableArray1 replaceObjectAtIndex: 1 withObject: cArray[1]]; + [mutableArray1 replaceObjectAtIndex: 2 withObject: cArray[2]]; ok = false; i = 0; @try { - for (OFString *s in m[0]) { - (void)s; + for (OFString *string in mutableArray1) { + (void)string; if (i == 0) - [m[0] addObject: @""]; + [mutableArray1 addObject: @""]; i++; } } @catch (OFEnumerationMutationException *e) { ok = true; } TEST(@"Detection of mutation during Fast Enumeration", ok) - [m[0] removeLastObject]; + [mutableArray1 removeLastObject]; #ifdef OF_HAVE_BLOCKS { - __block bool blockOk = true; - __block size_t count = 0; - OFArray *cmp = a[0]; - OFMutableArray *a2; - - m[0] = [[a[0] mutableCopy] autorelease]; - [m[0] enumerateObjectsUsingBlock: - ^ (id object, size_t idx, bool *stop) { - count++; - if (![object isEqual: [cmp objectAtIndex: idx]]) - blockOk = false; - }]; - - if (count != cmp.count) - blockOk = false; - - TEST(@"Enumeration using blocks", blockOk) - - blockOk = false; - a2 = m[0]; - @try { - [a2 enumerateObjectsUsingBlock: - ^ (id object, size_t idx, bool *stop) { - [a2 removeObjectAtIndex: idx]; - }]; - } @catch (OFEnumerationMutationException *e) { - blockOk = true; + __block bool blockOK = true; + __block size_t count = 0; + OFArray *compareArray = array1; + OFMutableArray *mutableArray3; + + mutableArray1 = [[array1 mutableCopy] autorelease]; + [mutableArray1 enumerateObjectsUsingBlock: + ^ (id object_, size_t idx, bool *stop) { + count++; + if (![object_ isEqual: + [compareArray objectAtIndex: idx]]) + blockOK = false; + }]; + + if (count != compareArray.count) + blockOK = false; + + TEST(@"Enumeration using blocks", blockOK) + + blockOK = false; + mutableArray3 = mutableArray1; + @try { + [mutableArray3 enumerateObjectsUsingBlock: + ^ (id object_, size_t idx, bool *stop) { + [mutableArray3 removeObjectAtIndex: idx]; + }]; + } @catch (OFEnumerationMutationException *e) { + blockOK = true; } @catch (OFOutOfRangeException *e) { /* * Out of bounds access due to enumeration not being * detected. */ } TEST(@"Detection of mutation during enumeration using blocks", - blockOk) + blockOK) } TEST(@"-[replaceObjectsUsingBlock:]", - R([m[0] replaceObjectsUsingBlock: ^ id (id object, size_t idx) { - switch (idx) { - case 0: - return @"foo"; - case 1: - return @"bar"; - } - - return nil; - }]) && [m[0].description isEqual: @"(\n\tfoo,\n\tbar\n)"]) + R([mutableArray1 replaceObjectsUsingBlock: + ^ id (id object_, size_t idx) { + switch (idx) { + case 0: + return @"foo"; + case 1: + return @"bar"; + } + + return nil; + }]) && [mutableArray1.description isEqual: @"(\n\tfoo,\n\tbar\n)"]) TEST(@"-[mappedArrayUsingBlock:]", - [[m[0] mappedArrayUsingBlock: ^ id (id object, size_t idx) { - switch (idx) { - case 0: - return @"foobar"; - case 1: - return @"qux"; - } - - return nil; + [[mutableArray1 mappedArrayUsingBlock: + ^ id (id object_, size_t idx) { + switch (idx) { + case 0: + return @"foobar"; + case 1: + return @"qux"; + } + + return nil; }].description isEqual: @"(\n\tfoobar,\n\tqux\n)"]) TEST(@"-[filteredArrayUsingBlock:]", - [[m[0] filteredArrayUsingBlock: ^ bool (id object, size_t idx) { - return [object isEqual: @"foo"]; + [[mutableArray1 filteredArrayUsingBlock: + ^ bool (id object_, size_t idx) { + return [object_ isEqual: @"foo"]; }].description isEqual: @"(\n\tfoo\n)"]) TEST(@"-[foldUsingBlock:]", [[arrayClass arrayWithObjects: [OFMutableString string], @"foo", @"bar", @"baz", nil] foldUsingBlock: ^ id (id left, id right) { - [left appendString: right]; - return left; + [left appendString: right]; + return left; }]) #endif TEST(@"-[valueForKey:]", [[[arrayClass arrayWithObjects: @"foo", @"bar", @"quxqux", nil] @@ -409,18 +426,18 @@ [arrayClass arrayWithObjects: [OFNumber numberWithInt: 3], [OFNumber numberWithInt: 3], [OFNumber numberWithInt: 6], nil]] && [[[arrayClass arrayWithObjects: @"1", @"2", nil] valueForKey: @"@count"] isEqual: [OFNumber numberWithInt: 2]]) - m[0] = [mutableArrayClass arrayWithObjects: + mutableArray1 = [mutableArrayClass arrayWithObjects: [OFMutableURL URLWithString: @"http://foo.bar/"], [OFMutableURL URLWithString: @"http://bar.qux/"], [OFMutableURL URLWithString: @"http://qux.quxqux/"], nil]; TEST(@"-[setValue:forKey:]", - R([m[0] setValue: [OFNumber numberWithShort: 1234] - forKey: @"port"]) && - [m[0] isEqual: [arrayClass arrayWithObjects: + R([mutableArray1 setValue: [OFNumber numberWithShort: 1234] + forKey: @"port"]) && + [mutableArray1 isEqual: [arrayClass arrayWithObjects: [OFURL URLWithString: @"http://foo.bar:1234/"], [OFURL URLWithString: @"http://bar.qux:1234/"], [OFURL URLWithString: @"http://qux.quxqux:1234/"], nil]]) objc_autoreleasePoolPop(pool); Index: tests/OFBlockTests.m ================================================================== --- tests/OFBlockTests.m +++ tests/OFBlockTests.m @@ -15,11 +15,11 @@ #include "config.h" #import "TestsAppDelegate.h" -static OFString *module = @"OFBlock"; +static OFString *const module = @"OFBlock"; #if defined(OF_OBJFW_RUNTIME) extern struct objc_class _NSConcreteStackBlock; extern struct objc_class _NSConcreteGlobalBlock; extern struct objc_class _NSConcreteMallocBlock; @@ -27,11 +27,11 @@ extern void *_NSConcreteStackBlock; extern void *_NSConcreteGlobalBlock; extern void *_NSConcreteMallocBlock; #endif -static void (^g)(void) = ^ {}; +static void (^globalBlock)(void) = ^ {}; static int (^returnStackBlock(void))(void) { __block int i = 42; @@ -41,70 +41,76 @@ static double forwardTest(void) { __block double d; - void (^b)(void) = Block_copy(^ { + void (^block)(void) = Block_copy(^ { d = 5; }); - b(); - Block_release(b); + block(); + Block_release(block); return d; } @implementation TestsAppDelegate (OFBlockTests) - (void)blockTests { void *pool = objc_autoreleasePoolPush(); __block int x; - void (^s)(void) = ^ { x = 0; }; - void (^m)(void); - int (^v)(void); + void (^stackBlock)(void) = ^ { + x = 0; + (void)x; + }; + void (^mallocBlock)(void); + int (^voidBlock)(void); TEST(@"Class of stack block", (Class)&_NSConcreteStackBlock == objc_getClass("OFStackBlock") && - [s isKindOfClass: [OFBlock class]]) + [stackBlock isKindOfClass: [OFBlock class]]) #if !defined(OF_WINDOWS) || !defined(__clang__) || !defined(OF_NO_SHARED) /* * Causes a linker error on Windows with Clang when compiling as a * static library. This is a bug in Clang. */ TEST(@"Class of global block", (Class)&_NSConcreteGlobalBlock == objc_getClass("OFGlobalBlock") && - [g isKindOfClass: [OFBlock class]]) + [globalBlock isKindOfClass: [OFBlock class]]) #endif TEST(@"Class of a malloc block", (Class)&_NSConcreteMallocBlock == objc_getClass("OFMallocBlock")) TEST(@"Copying a stack block", - (m = [[s copy] autorelease]) && - [m class] == objc_getClass("OFMallocBlock") && - [m isKindOfClass: [OFBlock class]]) + (mallocBlock = [[stackBlock copy] autorelease]) && + [mallocBlock class] == objc_getClass("OFMallocBlock") && + [mallocBlock isKindOfClass: [OFBlock class]]) TEST(@"Copying a stack block and referencing its variable", forwardTest() == 5) TEST(@"Copying a stack block and using its copied variable", - (v = returnStackBlock()) && v() == 43 && v() == 44 && v() == 45) + (voidBlock = returnStackBlock()) && voidBlock() == 43 && + voidBlock() == 44 && voidBlock() == 45) - TEST(@"Copying a global block", (id)g == [[g copy] autorelease]) + TEST(@"Copying a global block", + (id)globalBlock == [[globalBlock copy] autorelease]) #ifndef __clang_analyzer__ TEST(@"Copying a malloc block", - (id)m == [m copy] && [m retainCount] == 2) + (id)mallocBlock == [mallocBlock copy] && + [mallocBlock retainCount] == 2) #endif - TEST(@"Autorelease a stack block", R([s autorelease])) + TEST(@"Autorelease a stack block", R([stackBlock autorelease])) - TEST(@"Autorelease a global block", R([g autorelease])) + TEST(@"Autorelease a global block", R([globalBlock autorelease])) #ifndef __clang_analyzer__ - TEST(@"Autorelease a malloc block", R([m autorelease])) + TEST(@"Autorelease a malloc block", R([mallocBlock autorelease])) #endif objc_autoreleasePoolPop(pool); } @end Index: tests/OFCharacterSetTests.m ================================================================== --- tests/OFCharacterSetTests.m +++ tests/OFCharacterSetTests.m @@ -19,11 +19,11 @@ #import "OFCharacterSet.h" #import "OFBitSetCharacterSet.h" #import "OFRangeCharacterSet.h" -static OFString *module = nil; +static OFString *module; @interface SimpleCharacterSet: OFCharacterSet @end @implementation SimpleCharacterSet @@ -35,73 +35,73 @@ @implementation TestsAppDelegate (OFCharacterSetTests) - (void)characterSetTests { void *pool = objc_autoreleasePoolPush(); - OFCharacterSet *cs, *ics; + OFCharacterSet *characterSet, *invertedCharacterSet; bool ok; module = @"OFCharacterSet"; - cs = [[[SimpleCharacterSet alloc] init] autorelease]; + characterSet = [[[SimpleCharacterSet alloc] init] autorelease]; ok = true; for (OFUnichar c = 0; c < 65536; c++) { if (c % 2 == 0) { - if (![cs characterIsMember: c]) + if (![characterSet characterIsMember: c]) ok = false; - } else if ([cs characterIsMember: c]) + } else if ([characterSet characterIsMember: c]) ok = false; } TEST(@"-[characterIsMember:]", ok); module = @"OFBitSetCharacterSet"; TEST(@"+[characterSetWithCharactersInString:]", - (cs = [OFCharacterSet characterSetWithCharactersInString: + (characterSet = [OFCharacterSet characterSetWithCharactersInString: @"0123456789"]) && - [cs isKindOfClass: [OFBitSetCharacterSet class]]) + [characterSet isKindOfClass: [OFBitSetCharacterSet class]]) ok = true; for (OFUnichar c = 0; c < 65536; c++) { if (c >= '0' && c <= '9') { - if (![cs characterIsMember: c]) + if (![characterSet characterIsMember: c]) ok = false; - } else if ([cs characterIsMember: c]) + } else if ([characterSet characterIsMember: c]) ok = false; } TEST(@"-[characterIsMember:]", ok); module = @"OFRangeCharacterSet"; TEST(@"+[characterSetWithRange:]", - (cs = [OFCharacterSet + (characterSet = [OFCharacterSet characterSetWithRange: OFRangeMake('0', 10)]) && - [cs isKindOfClass: [OFRangeCharacterSet class]]) + [characterSet isKindOfClass: [OFRangeCharacterSet class]]) ok = true; for (OFUnichar c = 0; c < 65536; c++) { if (c >= '0' && c <= '9') { - if (![cs characterIsMember: c]) + if (![characterSet characterIsMember: c]) ok = false; - } else if ([cs characterIsMember: c]) + } else if ([characterSet characterIsMember: c]) ok = false; } TEST(@"-[characterIsMember:]", ok); ok = true; - ics = cs.invertedSet; + invertedCharacterSet = characterSet.invertedSet; for (OFUnichar c = 0; c < 65536; c++) { if (c >= '0' && c <= '9') { - if ([ics characterIsMember: c]) + if ([invertedCharacterSet characterIsMember: c]) ok = false; - } else if (![ics characterIsMember: c]) + } else if (![invertedCharacterSet characterIsMember: c]) ok = false; } TEST(@"-[invertedSet]", ok); TEST(@"Inverting -[invertedSet] returns original set", - ics.invertedSet == cs) + invertedCharacterSet.invertedSet == characterSet) objc_autoreleasePoolPop(pool); } @end Index: tests/OFDataTests.m ================================================================== --- tests/OFDataTests.m +++ tests/OFDataTests.m @@ -17,210 +17,212 @@ #include #import "TestsAppDelegate.h" -static OFString *module = @"OFData"; -const char *str = "Hello!"; +static OFString *const module = @"OFData"; @implementation TestsAppDelegate (OFDataTests) - (void)dataTests { void *pool = objc_autoreleasePoolPush(); - OFMutableData *mutable; - OFData *immutable; + OFMutableData *mutableData; + OFData *data; void *raw[2]; OFRange range; TEST(@"+[dataWithItemSize:]", - (mutable = [OFMutableData dataWithItemSize: 4096])) + (mutableData = [OFMutableData dataWithItemSize: 4096])) raw[0] = OFAllocMemory(1, 4096); raw[1] = OFAllocMemory(1, 4096); memset(raw[0], 0xFF, 4096); memset(raw[1], 0x42, 4096); - TEST(@"-[addItem:]", R([mutable addItem: raw[0]]) && - R([mutable addItem: raw[1]])) + TEST(@"-[addItem:]", R([mutableData addItem: raw[0]]) && + R([mutableData addItem: raw[1]])) TEST(@"-[itemAtIndex:]", - memcmp([mutable itemAtIndex: 0], raw[0], 4096) == 0 && - memcmp([mutable itemAtIndex: 1], raw[1], 4096) == 0) + memcmp([mutableData itemAtIndex: 0], raw[0], 4096) == 0 && + memcmp([mutableData itemAtIndex: 1], raw[1], 4096) == 0) - TEST(@"-[lastItem]", memcmp(mutable.lastItem, raw[1], 4096) == 0) + TEST(@"-[lastItem]", memcmp(mutableData.lastItem, raw[1], 4096) == 0) - TEST(@"-[count]", mutable.count == 2) + TEST(@"-[count]", mutableData.count == 2) TEST(@"-[isEqual:]", - (immutable = [OFData dataWithItems: mutable.items - count: mutable.count - itemSize: mutable.itemSize]) && - [immutable isEqual: mutable] && - R([mutable removeLastItem]) && ![mutable isEqual: immutable]) + (data = [OFData dataWithItems: mutableData.items + count: mutableData.count + itemSize: mutableData.itemSize]) && + [data isEqual: mutableData] && + R([mutableData removeLastItem]) && ![mutableData isEqual: data]) TEST(@"-[mutableCopy]", - (mutable = [[immutable mutableCopy] autorelease]) && - [mutable isEqual: immutable]) + (mutableData = [[data mutableCopy] autorelease]) && + [mutableData isEqual: data]) - TEST(@"-[compare]", [mutable compare: immutable] == 0 && - R([mutable removeLastItem]) && - [immutable compare: mutable] == OFOrderedDescending && - [mutable compare: immutable] == OFOrderedAscending && + TEST(@"-[compare]", [mutableData compare: data] == 0 && + R([mutableData removeLastItem]) && + [data compare: mutableData] == OFOrderedDescending && + [mutableData compare: data] == OFOrderedAscending && [[OFData dataWithItems: "aa" count: 2] compare: [OFData dataWithItems: "z" count: 1]] == OFOrderedAscending) - TEST(@"-[hash]", immutable.hash == 0x634A529F) + TEST(@"-[hash]", data.hash == 0x634A529F) - mutable = [OFMutableData dataWithItems: "abcdef" count: 6]; + mutableData = [OFMutableData dataWithItems: "abcdef" count: 6]; - TEST(@"-[removeLastItem]", R([mutable removeLastItem]) && - mutable.count == 5 && memcmp(mutable.items, "abcde", 5) == 0) + TEST(@"-[removeLastItem]", + R([mutableData removeLastItem]) && mutableData.count == 5 && + memcmp(mutableData.items, "abcde", 5) == 0) TEST(@"-[removeItemsInRange:]", - R([mutable removeItemsInRange: OFRangeMake(1, 2)]) && - mutable.count == 3 && memcmp(mutable.items, "ade", 3) == 0) + R([mutableData removeItemsInRange: OFRangeMake(1, 2)]) && + mutableData.count == 3 && memcmp(mutableData.items, "ade", 3) == 0) TEST(@"-[insertItems:atIndex:count:]", - R([mutable insertItems: "bc" atIndex: 1 count: 2]) && - mutable.count == 5 && memcmp(mutable.items, "abcde", 5) == 0) - - immutable = [OFData dataWithItems: "aaabaccdacaabb" - count: 7 - itemSize: 2]; - - range = [immutable rangeOfData: [OFData dataWithItems: "aa" - count: 1 - itemSize: 2] - options: 0 - range: OFRangeMake(0, 7)]; + R([mutableData insertItems: "bc" atIndex: 1 count: 2]) && + mutableData.count == 5 && + memcmp(mutableData.items, "abcde", 5) == 0) + + data = [OFData dataWithItems: "aaabaccdacaabb" count: 7 itemSize: 2]; + + range = [data rangeOfData: [OFData dataWithItems: "aa" + count: 1 + itemSize: 2] + options: 0 + range: OFRangeMake(0, 7)]; TEST(@"-[rangeOfData:options:range:] #1", range.location == 0 && range.length == 1) - range = [immutable rangeOfData: [OFData dataWithItems: "aa" - count: 1 - itemSize: 2] - options: OFDataSearchBackwards - range: OFRangeMake(0, 7)]; + range = [data rangeOfData: [OFData dataWithItems: "aa" + count: 1 + itemSize: 2] + options: OFDataSearchBackwards + range: OFRangeMake(0, 7)]; TEST(@"-[rangeOfData:options:range:] #2", range.location == 5 && range.length == 1) - range = [immutable rangeOfData: [OFData dataWithItems: "ac" - count: 1 - itemSize: 2] - options: 0 - range: OFRangeMake(0, 7)]; + range = [data rangeOfData: [OFData dataWithItems: "ac" + count: 1 + itemSize: 2] + options: 0 + range: OFRangeMake(0, 7)]; TEST(@"-[rangeOfData:options:range:] #3", range.location == 2 && range.length == 1) - range = [immutable rangeOfData: [OFData dataWithItems: "aabb" - count: 2 - itemSize: 2] - options: 0 - range: OFRangeMake(0, 7)]; + range = [data rangeOfData: [OFData dataWithItems: "aabb" + count: 2 + itemSize: 2] + options: 0 + range: OFRangeMake(0, 7)]; TEST(@"-[rangeOfData:options:range:] #4", range.location == 5 && range.length == 2) TEST(@"-[rangeOfData:options:range:] #5", - R(range = [immutable rangeOfData: [OFData dataWithItems: "aa" - count: 1 - itemSize: 2] - options: 0 - range: OFRangeMake(1, 6)]) && + R(range = [data rangeOfData: [OFData dataWithItems: "aa" + count: 1 + itemSize: 2] + options: 0 + range: OFRangeMake(1, 6)]) && range.location == 5 && range.length == 1) - range = [immutable rangeOfData: [OFData dataWithItems: "aa" - count: 1 - itemSize: 2] - options: OFDataSearchBackwards - range: OFRangeMake(0, 5)]; + range = [data rangeOfData: [OFData dataWithItems: "aa" + count: 1 + itemSize: 2] + options: OFDataSearchBackwards + range: OFRangeMake(0, 5)]; TEST(@"-[rangeOfData:options:range:] #6", range.location == 0 && range.length == 1) EXPECT_EXCEPTION( @"-[rangeOfData:options:range:] failing on different itemSize", OFInvalidArgumentException, - [immutable rangeOfData: [OFData dataWithItems: "aaa" - count: 1 - itemSize: 3] - options: 0 - range: OFRangeMake(0, 1)]) + [data rangeOfData: [OFData dataWithItems: "aaa" + count: 1 + itemSize: 3] + options: 0 + range: OFRangeMake(0, 1)]) EXPECT_EXCEPTION( @"-[rangeOfData:options:range:] failing on out of range", OFOutOfRangeException, - [immutable rangeOfData: [OFData dataWithItems: "" - count: 0 - itemSize: 2] - options: 0 - range: OFRangeMake(8, 1)]) + [data rangeOfData: [OFData dataWithItems: "" count: 0 itemSize: 2] + options: 0 + range: OFRangeMake(8, 1)]) TEST(@"-[subdataWithRange:]", - [[immutable subdataWithRange: OFRangeMake(2, 4)] - isEqual: [OFData dataWithItems: "accdacaa" - count: 4 - itemSize: 2]] && - [[mutable subdataWithRange: OFRangeMake(2, 3)] - isEqual: [OFData dataWithItems: "cde" - count: 3]]) + [[data subdataWithRange: OFRangeMake(2, 4)] + isEqual: [OFData dataWithItems: "accdacaa" count: 4 itemSize: 2]] && + [[mutableData subdataWithRange: OFRangeMake(2, 3)] + isEqual: [OFData dataWithItems: "cde" count: 3]]) EXPECT_EXCEPTION(@"-[subdataWithRange:] failing on out of range #1", OFOutOfRangeException, - [immutable subdataWithRange: OFRangeMake(7, 1)]) + [data subdataWithRange: OFRangeMake(7, 1)]) EXPECT_EXCEPTION(@"-[subdataWithRange:] failing on out of range #2", OFOutOfRangeException, - [mutable subdataWithRange: OFRangeMake(6, 1)]) + [mutableData subdataWithRange: OFRangeMake(6, 1)]) - TEST(@"-[stringByMD5Hashing]", [mutable.stringByMD5Hashing + TEST(@"-[stringByMD5Hashing]", + [mutableData.stringByMD5Hashing isEqual: @"ab56b4d92b40713acc5af89985d4b786"]) - TEST(@"-[stringByRIPEMD160Hashing]", [mutable.stringByRIPEMD160Hashing + TEST(@"-[stringByRIPEMD160Hashing]", + [mutableData.stringByRIPEMD160Hashing isEqual: @"973398b6e6c6cfa6b5e6a5173f195ce3274bf828"]) - TEST(@"-[stringBySHA1Hashing]", [mutable.stringBySHA1Hashing + TEST(@"-[stringBySHA1Hashing]", + [mutableData.stringBySHA1Hashing isEqual: @"03de6c570bfe24bfc328ccd7ca46b76eadaf4334"]) - TEST(@"-[stringBySHA224Hashing]", [mutable.stringBySHA224Hashing + TEST(@"-[stringBySHA224Hashing]", + [mutableData.stringBySHA224Hashing isEqual: @"bdd03d560993e675516ba5a50638b6531ac2ac3d5847c61916cfced6" ]) - TEST(@"-[stringBySHA256Hashing]", [mutable.stringBySHA256Hashing + TEST(@"-[stringBySHA256Hashing]", + [mutableData.stringBySHA256Hashing isEqual: @"36bbe50ed96841d10443bcb670d6554f0a34b761be67ec9c4a8ad2c0" @"c44ca42c"]) - TEST(@"-[stringBySHA384Hashing]", [mutable.stringBySHA384Hashing + TEST(@"-[stringBySHA384Hashing]", + [mutableData.stringBySHA384Hashing isEqual: @"4c525cbeac729eaf4b4665815bc5db0c84fe6300068a727cf74e2813" @"521565abc0ec57a37ee4d8be89d097c0d2ad52f0"]) - TEST(@"-[stringBySHA512Hashing]", [mutable.stringBySHA512Hashing + TEST(@"-[stringBySHA512Hashing]", + [mutableData.stringBySHA512Hashing isEqual: @"878ae65a92e86cac011a570d4c30a7eaec442b85ce8eca0c2952b5e3" @"cc0628c2e79d889ad4d5c7c626986d452dd86374b6ffaa7cd8b67665" @"bef2289a5c70b0a1"]) TEST(@"-[stringByBase64Encoding]", - [mutable.stringByBase64Encoding isEqual: @"YWJjZGU="]) + [mutableData.stringByBase64Encoding isEqual: @"YWJjZGU="]) TEST(@"+[dataWithBase64EncodedString:]", - memcmp([[OFData dataWithBase64EncodedString: @"YWJjZGU="] - items], "abcde", 5) == 0) + memcmp([[OFData dataWithBase64EncodedString: @"YWJjZGU="] items], + "abcde", 5) == 0) TEST(@"Building strings", - (mutable = [OFMutableData dataWithItems: str count: 6]) && - R([mutable addItem: ""]) && - strcmp(mutable.items, str) == 0) + (mutableData = [OFMutableData dataWithItems: "Hello!" count: 6]) && + R([mutableData addItem: ""]) && + strcmp(mutableData.items, "Hello!") == 0) EXPECT_EXCEPTION(@"Detect out of range in -[itemAtIndex:]", - OFOutOfRangeException, [mutable itemAtIndex: mutable.count]) + OFOutOfRangeException, [mutableData itemAtIndex: mutableData.count]) EXPECT_EXCEPTION(@"Detect out of range in -[addItems:count:]", - OFOutOfRangeException, [mutable addItems: raw[0] count: SIZE_MAX]) + OFOutOfRangeException, + [mutableData addItems: raw[0] count: SIZE_MAX]) EXPECT_EXCEPTION(@"Detect out of range in -[removeItemsInRange:]", OFOutOfRangeException, - [mutable removeItemsInRange: OFRangeMake(mutable.count, 1)]) + [mutableData removeItemsInRange: OFRangeMake(mutableData.count, 1)]) OFFreeMemory(raw[0]); OFFreeMemory(raw[1]); objc_autoreleasePoolPop(pool); } @end Index: tests/OFDateTests.m ================================================================== --- tests/OFDateTests.m +++ tests/OFDateTests.m @@ -17,17 +17,17 @@ #include #import "TestsAppDelegate.h" -static OFString *module = @"OFDate"; +static OFString *const module = @"OFDate"; @implementation TestsAppDelegate (OFDateTests) - (void)dateTests { void *pool = objc_autoreleasePoolPush(); - OFDate *d1, *d2; + OFDate *date1, *date2; struct tm tm; int16_t tz; const char *dstr = "Wed, 09 Jun 2021 +0200x"; TEST(@"OFStrPTime()", @@ -34,18 +34,18 @@ OFStrPTime(dstr, "%a, %d %b %Y %z", &tm, &tz) == dstr + 22 && tm.tm_wday == 3 && tm.tm_mday == 9 && tm.tm_mon == 5 && tm.tm_year == 2021 - 1900 && tz == 2 * 60) TEST(@"+[dateWithTimeIntervalSince1970:]", - (d1 = [OFDate dateWithTimeIntervalSince1970: 0])) + (date1 = [OFDate dateWithTimeIntervalSince1970: 0])) TEST(@"-[dateByAddingTimeInterval:]", - (d2 = [d1 dateByAddingTimeInterval: 3600 * 25 + 5.000002])) + (date2 = [date1 dateByAddingTimeInterval: 3600 * 25 + 5.000002])) TEST(@"-[description]", - [d1.description isEqual: @"1970-01-01T00:00:00Z"] && - [d2.description isEqual: @"1970-01-02T01:00:05Z"]) + [date1.description isEqual: @"1970-01-01T00:00:00Z"] && + [date2.description isEqual: @"1970-01-02T01:00:05Z"]) TEST(@"+[dateWithDateString:format:]", [[[OFDate dateWithDateString: @"2000-06-20T12:34:56+0200" format: @"%Y-%m-%dT%H:%M:%S%z"] description] isEqual: @"2000-06-20T10:34:56Z"]); @@ -75,35 +75,37 @@ @"+[dateWithLocalDateString:format:] #2", OFInvalidFormatException, [OFDate dateWithLocalDateString: @"2000-06-20T12:34:56+0200x" format: @"%Y-%m-%dT%H:%M:%S%z"]) TEST(@"-[isEqual:]", - [d1 isEqual: [OFDate dateWithTimeIntervalSince1970: 0]] && - ![d1 isEqual: [OFDate dateWithTimeIntervalSince1970: 0.0000001]]) - - TEST(@"-[compare:]", [d1 compare: d2] == OFOrderedAscending) - - TEST(@"-[second]", d1.second == 0 && d2.second == 5) - - TEST(@"-[microsecond]", d1.microsecond == 0 && d2.microsecond == 2) - - TEST(@"-[minute]", d1.minute == 0 && d2.minute == 0) - - TEST(@"-[hour]", d1.hour == 0 && d2.hour == 1) - - TEST(@"-[dayOfMonth]", d1.dayOfMonth == 1 && d2.dayOfMonth == 2) - - TEST(@"-[monthOfYear]", d1.monthOfYear == 1 && d2.monthOfYear == 1) - - TEST(@"-[year]", d1.year == 1970 && d2.year == 1970) - - TEST(@"-[dayOfWeek]", d1.dayOfWeek == 4 && d2.dayOfWeek == 5) - - TEST(@"-[dayOfYear]", d1.dayOfYear == 1 && d2.dayOfYear == 2) - - TEST(@"-[earlierDate:]", [[d1 earlierDate: d2] isEqual: d1]) - - TEST(@"-[laterDate:]", [[d1 laterDate: d2] isEqual: d2]) + [date1 isEqual: [OFDate dateWithTimeIntervalSince1970: 0]] && + ![date1 isEqual: [OFDate dateWithTimeIntervalSince1970: 0.0000001]]) + + TEST(@"-[compare:]", [date1 compare: date2] == OFOrderedAscending) + + TEST(@"-[second]", date1.second == 0 && date2.second == 5) + + TEST(@"-[microsecond]", + date1.microsecond == 0 && date2.microsecond == 2) + + TEST(@"-[minute]", date1.minute == 0 && date2.minute == 0) + + TEST(@"-[hour]", date1.hour == 0 && date2.hour == 1) + + TEST(@"-[dayOfMonth]", date1.dayOfMonth == 1 && date2.dayOfMonth == 2) + + TEST(@"-[monthOfYear]", + date1.monthOfYear == 1 && date2.monthOfYear == 1) + + TEST(@"-[year]", date1.year == 1970 && date2.year == 1970) + + TEST(@"-[dayOfWeek]", date1.dayOfWeek == 4 && date2.dayOfWeek == 5) + + TEST(@"-[dayOfYear]", date1.dayOfYear == 1 && date2.dayOfYear == 2) + + TEST(@"-[earlierDate:]", [[date1 earlierDate: date2] isEqual: date1]) + + TEST(@"-[laterDate:]", [[date1 laterDate: date2] isEqual: date2]) objc_autoreleasePoolPop(pool); } @end Index: tests/OFDictionaryTests.m ================================================================== --- tests/OFDictionaryTests.m +++ tests/OFDictionaryTests.m @@ -15,11 +15,11 @@ #include "config.h" #import "TestsAppDelegate.h" -static OFString *module = nil; +static OFString *module; static OFString *keys[] = { @"key1", @"key2" }; static OFString *values[] = { @@ -102,11 +102,11 @@ return [_dictionary objectForKey: key]; } - (size_t)count { - return [_dictionary count]; + return _dictionary.count; } - (OFEnumerator *)keyEnumerator { return [_dictionary keyEnumerator]; @@ -157,100 +157,101 @@ @implementation TestsAppDelegate (OFDictionaryTests) - (void)dictionaryTestsWithClass: (Class)dictionaryClass mutableClass: (Class)mutableDictionaryClass { void *pool = objc_autoreleasePoolPush(); - OFMutableDictionary *mutDict = [mutableDictionaryClass dictionary]; + OFMutableDictionary *mutableDict = [mutableDictionaryClass dictionary]; OFDictionary *dict; OFEnumerator *keyEnumerator, *objectEnumerator; OFArray *keysArray, *valuesArray; - [mutDict setObject: values[0] forKey: keys[0]]; - [mutDict setValue: values[1] forKey: keys[1]]; + [mutableDict setObject: values[0] forKey: keys[0]]; + [mutableDict setValue: values[1] forKey: keys[1]]; TEST(@"-[objectForKey:]", - [[mutDict objectForKey: keys[0]] isEqual: values[0]] && - [[mutDict objectForKey: keys[1]] isEqual: values[1]] && - [mutDict objectForKey: @"key3"] == nil) + [[mutableDict objectForKey: keys[0]] isEqual: values[0]] && + [[mutableDict objectForKey: keys[1]] isEqual: values[1]] && + [mutableDict objectForKey: @"key3"] == nil) TEST(@"-[valueForKey:]", - [[mutDict valueForKey: keys[0]] isEqual: values[0]] && - [[mutDict valueForKey: @"@count"] isEqual: + [[mutableDict valueForKey: keys[0]] isEqual: values[0]] && + [[mutableDict valueForKey: @"@count"] isEqual: [OFNumber numberWithInt: 2]]) EXPECT_EXCEPTION(@"Catching -[setValue:forKey:] on immutable " @"dictionary", OFUndefinedKeyException, [[dictionaryClass dictionary] setValue: @"x" forKey: @"x"]) TEST(@"-[containsObject:]", - [mutDict containsObject: values[0]] && - ![mutDict containsObject: @"nonexistent"]) + [mutableDict containsObject: values[0]] && + ![mutableDict containsObject: @"nonexistent"]) TEST(@"-[containsObjectIdenticalTo:]", - [mutDict containsObjectIdenticalTo: values[0]] && - ![mutDict containsObjectIdenticalTo: + [mutableDict containsObjectIdenticalTo: values[0]] && + ![mutableDict containsObjectIdenticalTo: [OFString stringWithString: values[0]]]) TEST(@"-[description]", - [[mutDict description] isEqual: + [[mutableDict description] isEqual: @"{\n\tkey1 = value1;\n\tkey2 = value2;\n}"]) TEST(@"-[allKeys]", - [[mutDict allKeys] isEqual: [OFArray arrayWithObjects: keys[0], - keys[1], nil]]) + [[mutableDict allKeys] isEqual: + [OFArray arrayWithObjects: keys[0], keys[1], nil]]) TEST(@"-[allObjects]", - [[mutDict allObjects] isEqual: [OFArray arrayWithObjects: values[0], - values[1], nil]]) + [[mutableDict allObjects] isEqual: + [OFArray arrayWithObjects: values[0], values[1], nil]]) - TEST(@"-[keyEnumerator]", (keyEnumerator = [mutDict keyEnumerator])) + TEST(@"-[keyEnumerator]", (keyEnumerator = [mutableDict keyEnumerator])) TEST(@"-[objectEnumerator]", - (objectEnumerator = [mutDict objectEnumerator])) + (objectEnumerator = [mutableDict objectEnumerator])) TEST(@"OFEnumerator's -[nextObject]", [[keyEnumerator nextObject] isEqual: keys[0]] && [[objectEnumerator nextObject] isEqual: values[0]] && [[keyEnumerator nextObject] isEqual: keys[1]] && [[objectEnumerator nextObject] isEqual: values[1]] && [keyEnumerator nextObject] == nil && [objectEnumerator nextObject] == nil) - [mutDict removeObjectForKey: keys[0]]; + [mutableDict removeObjectForKey: keys[0]]; EXPECT_EXCEPTION(@"Detection of mutation during enumeration", OFEnumerationMutationException, [keyEnumerator nextObject]); - [mutDict setObject: values[0] forKey: keys[0]]; + [mutableDict setObject: values[0] forKey: keys[0]]; size_t i = 0; bool ok = true; - for (OFString *key in mutDict) { + for (OFString *key in mutableDict) { if (i > 1 || ![key isEqual: keys[i]]) { ok = false; break; } - [mutDict setObject: [mutDict objectForKey: key] forKey: key]; + [mutableDict setObject: [mutableDict objectForKey: key] + forKey: key]; i++; } TEST(@"Fast Enumeration", ok) ok = false; @try { - for (OFString *key in mutDict) { + for (OFString *key in mutableDict) { (void)key; - [mutDict setObject: @"" forKey: @""]; + [mutableDict setObject: @"" forKey: @""]; } } @catch (OFEnumerationMutationException *e) { ok = true; } TEST(@"Detection of mutation during Fast Enumeration", ok) - [mutDict removeObjectForKey: @""]; + [mutableDict removeObjectForKey: @""]; TEST(@"-[stringByURLEncoding]", [[[OFDictionary dictionaryWithKeysAndObjects: @"foo", @"bar", @"q&x", @"q=x", nil] stringByURLEncoding] isEqual: @"q%26x=q%3Dx&foo=bar"]) @@ -258,71 +259,71 @@ #ifdef OF_HAVE_BLOCKS { __block size_t j = 0; __block bool blockOk = true; - [mutDict enumerateKeysAndObjectsUsingBlock: + [mutableDict enumerateKeysAndObjectsUsingBlock: ^ (id key, id object, bool *stop) { if (j > 1 || ![key isEqual: keys[j]]) { blockOk = false; *stop = true; return; } - [mutDict setObject: [mutDict objectForKey: key] - forKey: key]; + [mutableDict setObject: [mutableDict objectForKey: key] + forKey: key]; j++; }]; TEST(@"Enumeration using blocks", blockOk) blockOk = false; @try { - [mutDict enumerateKeysAndObjectsUsingBlock: + [mutableDict enumerateKeysAndObjectsUsingBlock: ^ (id key, id object, bool *stop) { - [mutDict setObject: @"" - forKey: @""]; + [mutableDict setObject: @"" forKey: @""]; }]; } @catch (OFEnumerationMutationException *e) { blockOk = true; } TEST(@"Detection of mutation during enumeration using blocks", blockOk) - [mutDict removeObjectForKey: @""]; + [mutableDict removeObjectForKey: @""]; } TEST(@"-[replaceObjectsUsingBlock:]", - R([mutDict replaceObjectsUsingBlock: ^ id (id key, id object) { - if ([key isEqual: keys[0]]) - return @"value_1"; - if ([key isEqual: keys[1]]) - return @"value_2"; - - return nil; - }]) && [[mutDict objectForKey: keys[0]] isEqual: @"value_1"] && - [[mutDict objectForKey: keys[1]] isEqual: @"value_2"]) + R([mutableDict replaceObjectsUsingBlock: ^ id (id key, id object) { + if ([key isEqual: keys[0]]) + return @"value_1"; + if ([key isEqual: keys[1]]) + return @"value_2"; + + return nil; + }]) && [[mutableDict objectForKey: keys[0]] isEqual: @"value_1"] && + [[mutableDict objectForKey: keys[1]] isEqual: @"value_2"]) TEST(@"-[mappedDictionaryUsingBlock:]", - [[[mutDict mappedDictionaryUsingBlock: ^ id (id key, id object) { - if ([key isEqual: keys[0]]) - return @"val1"; - if ([key isEqual: keys[1]]) - return @"val2"; + [[[mutableDict mappedDictionaryUsingBlock: + ^ id (id key, id object) { + if ([key isEqual: keys[0]]) + return @"val1"; + if ([key isEqual: keys[1]]) + return @"val2"; return nil; }] description] isEqual: @"{\n\tkey1 = val1;\n\tkey2 = val2;\n}"]) TEST(@"-[filteredDictionaryUsingBlock:]", - [[[mutDict filteredDictionaryUsingBlock: - ^ bool (id key, id object) { - return [key isEqual: keys[0]]; + [[[mutableDict filteredDictionaryUsingBlock: + ^ bool (id key, id object) { + return [key isEqual: keys[0]]; }] description] isEqual: @"{\n\tkey1 = value_1;\n}"]) #endif - TEST(@"-[count]", mutDict.count == 2) + TEST(@"-[count]", mutableDict.count == 2) TEST(@"+[dictionaryWithKeysAndObjects:]", (dict = [dictionaryClass dictionaryWithKeysAndObjects: @"foo", @"bar", @"baz", @"qux", nil]) && [[dict objectForKey: @"foo"] isEqual: @"bar"] && @@ -345,30 +346,30 @@ (dict = [[dict copy] autorelease]) && [[dict objectForKey: keys[0]] isEqual: values[0]] && [[dict objectForKey: keys[1]] isEqual: values[1]]) TEST(@"-[mutableCopy]", - (mutDict = [[dict mutableCopy] autorelease]) && - mutDict.count == dict.count && - [[mutDict objectForKey: keys[0]] isEqual: values[0]] && - [[mutDict objectForKey: keys[1]] isEqual: values[1]] && - R([mutDict setObject: @"value3" forKey: @"key3"]) && - [[mutDict objectForKey: @"key3"] isEqual: @"value3"] && - [[mutDict objectForKey: keys[0]] isEqual: values[0]] && - R([mutDict setObject: @"foo" forKey: keys[0]]) && - [[mutDict objectForKey: keys[0]] isEqual: @"foo"]) + (mutableDict = [[dict mutableCopy] autorelease]) && + mutableDict.count == dict.count && + [[mutableDict objectForKey: keys[0]] isEqual: values[0]] && + [[mutableDict objectForKey: keys[1]] isEqual: values[1]] && + R([mutableDict setObject: @"value3" forKey: @"key3"]) && + [[mutableDict objectForKey: @"key3"] isEqual: @"value3"] && + [[mutableDict objectForKey: keys[0]] isEqual: values[0]] && + R([mutableDict setObject: @"foo" forKey: keys[0]]) && + [[mutableDict objectForKey: keys[0]] isEqual: @"foo"]) TEST(@"-[removeObjectForKey:]", - R([mutDict removeObjectForKey: keys[0]]) && - [mutDict objectForKey: keys[0]] == nil) - - [mutDict setObject: @"foo" forKey: keys[0]]; - TEST(@"-[isEqual:]", ![mutDict isEqual: dict] && - R([mutDict removeObjectForKey: @"key3"]) && - ![mutDict isEqual: dict] && - R([mutDict setObject: values[0] forKey: keys[0]]) && - [mutDict isEqual: dict]) + R([mutableDict removeObjectForKey: keys[0]]) && + [mutableDict objectForKey: keys[0]] == nil) + + [mutableDict setObject: @"foo" forKey: keys[0]]; + TEST(@"-[isEqual:]", ![mutableDict isEqual: dict] && + R([mutableDict removeObjectForKey: @"key3"]) && + ![mutableDict isEqual: dict] && + R([mutableDict setObject: values[0] forKey: keys[0]]) && + [mutableDict isEqual: dict]) objc_autoreleasePoolPop(pool); } - (void)dictionaryTests Index: tests/OFHMACTests.m ================================================================== --- tests/OFHMACTests.m +++ tests/OFHMACTests.m @@ -17,109 +17,106 @@ #include #import "TestsAppDelegate.h" -static OFString *module = @"OFHMAC"; +static OFString *const module = @"OFHMAC"; static const uint8_t key[] = "yM9h8K6IWnJRvxC/0F8XRWG7RnACDBz8wqK2tbXrYVLoKC3vPLeJikyJSM47tVHc" "DlXHww9zULAC2sJUlm2Kg1z4oz2aXY3Y1PQSB4VkC/m0DQ7hCI6cAg4TWnKdzWTy" "cvYGX+Y6HWeDY79/PGSd8fNItme6I8w4HDBqU7BP2sum3jbePJqoiSnhcyJZQTeZ" "jw0ZXoyrfHgOYD2M+NsTDaGpLblFtQ7n5CczjKtafG40PkEwx1dcrd46U9i3GyTK"; -static const size_t key_length = sizeof(key); -static const uint8_t digest_md5[] = +static const size_t keyLength = sizeof(key); +static const uint8_t MD5Digest[] = "\xCC\x1F\xEF\x09\x29\xA3\x25\x1A\x06\xA9\x83\x99\xF9\xBC\x8F\x42"; -static const uint8_t digest_sha1[] = +static const uint8_t SHA1Digest[] = "\x94\xB9\x0A\x6F\xFB\xA7\x13\x6A\x75\x55" "\xD5\x7F\x5D\xB7\xF4\xCA\xEB\x4A\xDE\xBF"; -static const uint8_t digest_rmd160[] = +static const uint8_t RIPEMD160Digest[] = "\x2C\xE1\xED\x41\xC6\xF3\x51\xA8\x04\xD2" "\xC3\x9B\x08\x33\x3B\xD5\xC9\x00\x39\x50"; -static const uint8_t digest_sha256[] = +static const uint8_t SHA256Digest[] = "\xFB\x8C\xDA\x88\xB3\x81\x32\x16\xD7\xD8\x62\xD4\xA6\x26\x9D\x77" "\x01\x99\x62\x65\x29\x02\x41\xE6\xEF\xA1\x02\x31\xA8\x9D\x77\x5D"; -static const uint8_t digest_sha384[] = +static const uint8_t SHA384Digest[] = "\x2F\x4A\x47\xAE\x13\x8E\x96\x52\xF1\x8F\x05\xFD\x65\xCD\x9A\x97" "\x93\x2F\xC9\x02\xD6\xC6\xAB\x2E\x15\x76\xC0\xA7\xA0\x05\xF4\xEF" "\x14\x52\x33\x4B\x9C\x5F\xD8\x07\x4E\x98\xAE\x97\x46\x29\x24\xB4"; -static const uint8_t digest_sha512[] = +static const uint8_t SHA512Digest[] = "\xF5\x8C\x3F\x9C\xA2\x2F\x0A\xF3\x26\xD8\xC0\x7E\x20\x63\x88\x61" "\xC9\xE1\x1F\xD7\xC7\xE5\x59\x33\xD5\x2F\xAF\x56\x1C\x94\xC8\xA4" "\x61\xB3\xF9\x1A\xE3\x09\x43\xA6\x5B\x85\xB1\x50\x5B\xCB\x1A\x2E" "\xB7\xE8\x87\xC1\x73\x19\x63\xF6\xA2\x91\x8D\x7E\x2E\xCC\xEC\x99"; @implementation TestsAppDelegate (OFHMACTests) - (void)HMACTests { void *pool = objc_autoreleasePoolPush(); - OFFile *f = [OFFile fileWithPath: @"testfile.bin" mode: @"r"]; - OFHMAC *HMAC_MD5, *HMAC_SHA1, *HMAC_RMD160; - OFHMAC *HMAC_SHA256, *HMAC_SHA384, *HMAC_SHA512; + OFFile *file = [OFFile fileWithPath: @"testfile.bin" mode: @"r"]; + OFHMAC *HMACMD5, *HMACSHA1, *HMACRMD160; + OFHMAC *HMACSHA256, *HMACSHA384, *HMACSHA512; TEST(@"+[HMACWithHashClass:] with MD5", - (HMAC_MD5 = [OFHMAC HMACWithHashClass: [OFMD5Hash class] - allowsSwappableMemory: true])) + (HMACMD5 = [OFHMAC HMACWithHashClass: [OFMD5Hash class] + allowsSwappableMemory: true])) TEST(@"+[HMACWithHashClass:] with SHA-1", - (HMAC_SHA1 = [OFHMAC HMACWithHashClass: [OFSHA1Hash class] - allowsSwappableMemory: true])) + (HMACSHA1 = [OFHMAC HMACWithHashClass: [OFSHA1Hash class] + allowsSwappableMemory: true])) TEST(@"+[HMACWithHashClass:] with RIPEMD-160", - (HMAC_RMD160 = [OFHMAC HMACWithHashClass: [OFRIPEMD160Hash class] - allowsSwappableMemory: true])) + (HMACRMD160 = [OFHMAC HMACWithHashClass: [OFRIPEMD160Hash class] + allowsSwappableMemory: true])) TEST(@"+[HMACWithHashClass:] with SHA-256", - (HMAC_SHA256 = [OFHMAC HMACWithHashClass: [OFSHA256Hash class] - allowsSwappableMemory: true])) + (HMACSHA256 = [OFHMAC HMACWithHashClass: [OFSHA256Hash class] + allowsSwappableMemory: true])) TEST(@"+[HMACWithHashClass:] with SHA-384", - (HMAC_SHA384 = [OFHMAC HMACWithHashClass: [OFSHA384Hash class] - allowsSwappableMemory: true])) + (HMACSHA384 = [OFHMAC HMACWithHashClass: [OFSHA384Hash class] + allowsSwappableMemory: true])) TEST(@"+[HMACWithHashClass:] with SHA-512", - (HMAC_SHA512 = [OFHMAC HMACWithHashClass: [OFSHA512Hash class] - allowsSwappableMemory: true])) + (HMACSHA512 = [OFHMAC HMACWithHashClass: [OFSHA512Hash class] + allowsSwappableMemory: true])) EXPECT_EXCEPTION(@"Detection of missing key", - OFInvalidArgumentException, [HMAC_MD5 updateWithBuffer: "" - length: 0]) + OFInvalidArgumentException, + [HMACMD5 updateWithBuffer: "" length: 0]) TEST(@"-[setKey:length:] with MD5", - R([HMAC_MD5 setKey: key length: key_length])) - TEST(@"-[setKey:length:] with SHA-1", - R([HMAC_SHA1 setKey: key length: key_length])) - TEST(@"-[setKey:length:] with RIPEMD-160", - R([HMAC_RMD160 setKey: key length: key_length])) - TEST(@"-[setKey:length:] with SHA-256", - R([HMAC_SHA256 setKey: key length: key_length])) - TEST(@"-[setKey:length:] with SHA-384", - R([HMAC_SHA384 setKey: key length: key_length])) - TEST(@"-[setKey:length:] with SHA-512", - R([HMAC_SHA512 setKey: key length: key_length])) - - while (!f.atEndOfStream) { - char buf[64]; - size_t len = [f readIntoBuffer: buf length: 64]; - [HMAC_MD5 updateWithBuffer: buf length: len]; - [HMAC_SHA1 updateWithBuffer: buf length: len]; - [HMAC_RMD160 updateWithBuffer: buf length: len]; - [HMAC_SHA256 updateWithBuffer: buf length: len]; - [HMAC_SHA384 updateWithBuffer: buf length: len]; - [HMAC_SHA512 updateWithBuffer: buf length: len]; - } - [f close]; + R([HMACMD5 setKey: key length: keyLength])) + TEST(@"-[setKey:length:] with SHA-1", + R([HMACSHA1 setKey: key length: keyLength])) + TEST(@"-[setKey:length:] with RIPEMD-160", + R([HMACRMD160 setKey: key length: keyLength])) + TEST(@"-[setKey:length:] with SHA-256", + R([HMACSHA256 setKey: key length: keyLength])) + TEST(@"-[setKey:length:] with SHA-384", + R([HMACSHA384 setKey: key length: keyLength])) + TEST(@"-[setKey:length:] with SHA-512", + R([HMACSHA512 setKey: key length: keyLength])) + + while (!file.atEndOfStream) { + char buffer[64]; + size_t length = [file readIntoBuffer: buffer length: 64]; + [HMACMD5 updateWithBuffer: buffer length: length]; + [HMACSHA1 updateWithBuffer: buffer length: length]; + [HMACRMD160 updateWithBuffer: buffer length: length]; + [HMACSHA256 updateWithBuffer: buffer length: length]; + [HMACSHA384 updateWithBuffer: buffer length: length]; + [HMACSHA512 updateWithBuffer: buffer length: length]; + } + [file close]; TEST(@"-[digest] with MD5", - memcmp(HMAC_MD5.digest, digest_md5, HMAC_MD5.digestSize) == 0) + memcmp(HMACMD5.digest, MD5Digest, HMACMD5.digestSize) == 0) TEST(@"-[digest] with SHA-1", - memcmp(HMAC_SHA1.digest, digest_sha1, HMAC_SHA1.digestSize) == 0) + memcmp(HMACSHA1.digest, SHA1Digest, HMACSHA1.digestSize) == 0) TEST(@"-[digest] with RIPEMD-160", - memcmp(HMAC_RMD160.digest, digest_rmd160, - HMAC_RMD160.digestSize) == 0) + memcmp(HMACRMD160.digest, RIPEMD160Digest, + HMACRMD160.digestSize) == 0) TEST(@"-[digest] with SHA-256", - memcmp(HMAC_SHA256.digest, digest_sha256, - HMAC_SHA256.digestSize) == 0) + memcmp(HMACSHA256.digest, SHA256Digest, HMACSHA256.digestSize) == 0) TEST(@"-[digest] with SHA-384", - memcmp(HMAC_SHA384.digest, digest_sha384, - HMAC_SHA384.digestSize) == 0) + memcmp(HMACSHA384.digest, SHA384Digest, HMACSHA384.digestSize) == 0) TEST(@"-[digest] with SHA-512", - memcmp(HMAC_SHA512.digest, digest_sha512, - HMAC_SHA512.digestSize) == 0) + memcmp(HMACSHA512.digest, SHA512Digest, HMACSHA512.digestSize) == 0) objc_autoreleasePoolPop(pool); } @end Index: tests/OFHTTPClientTests.m ================================================================== --- tests/OFHTTPClientTests.m +++ tests/OFHTTPClientTests.m @@ -18,12 +18,12 @@ #include #include #import "TestsAppDelegate.h" -static OFString *module = @"OFHTTPClient"; -static OFCondition *cond; +static OFString *const module = @"OFHTTPClient"; +static OFCondition *condition; static OFHTTPResponse *response = nil; @interface TestsAppDelegate (HTTPClientTests) @end @@ -38,44 +38,35 @@ - (id)main { OFTCPSocket *listener, *client; char buffer[5]; - [cond lock]; + [condition lock]; listener = [OFTCPSocket socket]; _port = [listener bindToHost: @"127.0.0.1" port: 0]; [listener listen]; - [cond signal]; - [cond unlock]; + [condition signal]; + [condition unlock]; client = [listener accept]; - if (![[client readLine] isEqual: @"GET /foo HTTP/1.1"]) - OFEnsure(0); - - if (![[client readLine] hasPrefix: @"User-Agent:"]) - OFEnsure(0); - - if (![[client readLine] isEqual: @"Content-Length: 5"]) - OFEnsure(0); - - if (![[client readLine] isEqual: - @"Content-Type: application/x-www-form-urlencoded; charset=UTF-8"]) - OFEnsure(0); + OFEnsure([[client readLine] isEqual: @"GET /foo HTTP/1.1"]); + OFEnsure([[client readLine] hasPrefix: @"User-Agent:"]); + OFEnsure([[client readLine] isEqual: @"Content-Length: 5"]); + OFEnsure([[client readLine] isEqual: + @"Content-Type: application/x-www-form-urlencoded; charset=UTF-8"]); if (![[client readLine] isEqual: [OFString stringWithFormat: @"Host: 127.0.0.1:%" @PRIu16, _port]]) OFEnsure(0); - if (![[client readLine] isEqual: @""]) - OFEnsure(0); + OFEnsure([[client readLine] isEqual: @""]); [client readIntoBuffer: buffer exactLength: 5]; - if (memcmp(buffer, "Hello", 5) != 0) - OFEnsure(0); + OFEnsure(memcmp(buffer, "Hello", 5) == 0); [client writeString: @"HTTP/1.0 200 OK\r\n" @"cONTeNT-lENgTH: 7\r\n" @"\r\n" @"foo\n" @@ -113,19 +104,19 @@ OFURL *URL; OFHTTPClient *client; OFHTTPRequest *request; OFData *data; - cond = [OFCondition condition]; - [cond lock]; + condition = [OFCondition condition]; + [condition lock]; server = [[[HTTPClientTestsServer alloc] init] autorelease]; server.supportsSockets = true; [server start]; - [cond wait]; - [cond unlock]; + [condition wait]; + [condition unlock]; URL = [OFURL URLWithString: [OFString stringWithFormat: @"http://127.0.0.1:%" @PRIu16 "/foo", server->_port]]; Index: tests/OFHTTPCookieManagerTests.m ================================================================== --- tests/OFHTTPCookieManagerTests.m +++ tests/OFHTTPCookieManagerTests.m @@ -15,89 +15,89 @@ #include "config.h" #import "TestsAppDelegate.h" -static OFString *module = @"OFHTTPCookieManager"; +static OFString *const module = @"OFHTTPCookieManager"; @implementation TestsAppDelegate (OFHTTPCookieManagerTests) - (void)HTTPCookieManagerTests { void *pool = objc_autoreleasePoolPush(); OFHTTPCookieManager *manager = [OFHTTPCookieManager manager]; - OFURL *URL[4]; - OFHTTPCookie *cookie[5]; - - URL[0] = [OFURL URLWithString: @"http://nil.im/foo"]; - URL[1] = [OFURL URLWithString: @"https://nil.im/foo/bar"]; - URL[2] = [OFURL URLWithString: @"https://test.nil.im/foo/bar"]; - URL[3] = [OFURL URLWithString: @"http://webkeks.org/foo/bar"]; - - cookie[0] = [OFHTTPCookie cookieWithName: @"test" - value: @"1" - domain: @"nil.im"]; - TEST(@"-[addCookie:forURL:] #1", R([manager addCookie: cookie[0] - forURL: URL[0]])) + OFURL *URL1, *URL2, *URL3, *URL4; + OFHTTPCookie *cookie1, *cookie2, *cookie3, *cookie4, *cookie5; + + URL1 = [OFURL URLWithString: @"http://nil.im/foo"]; + URL2 = [OFURL URLWithString: @"https://nil.im/foo/bar"]; + URL3 = [OFURL URLWithString: @"https://test.nil.im/foo/bar"]; + URL4 = [OFURL URLWithString: @"http://webkeks.org/foo/bar"]; + + cookie1 = [OFHTTPCookie cookieWithName: @"test" + value: @"1" + domain: @"nil.im"]; + TEST(@"-[addCookie:forURL:] #1", + R([manager addCookie: cookie1 forURL: URL1])) TEST(@"-[cookiesForURL:] #1", - [[manager cookiesForURL: URL[0]] isEqual: - [OFArray arrayWithObject: cookie[0]]]) + [[manager cookiesForURL: URL1] isEqual: + [OFArray arrayWithObject: cookie1]]) - cookie[1] = [OFHTTPCookie cookieWithName: @"test" - value: @"2" - domain: @"webkeks.org"]; + cookie2 = [OFHTTPCookie cookieWithName: @"test" + value: @"2" + domain: @"webkeks.org"]; TEST(@"-[addCookie:forURL:] #2", - R([manager addCookie: cookie[1] forURL: URL[0]])) + R([manager addCookie: cookie2 forURL: URL1])) TEST(@"-[cookiesForURL:] #2", - [[manager cookiesForURL: URL[0]] isEqual: - [OFArray arrayWithObject: cookie[0]]] && - [[manager cookiesForURL: URL[3]] isEqual: [OFArray array]]) - - cookie[2] = [OFHTTPCookie cookieWithName: @"test" - value: @"3" - domain: @"nil.im"]; - cookie[2].secure = true; + [[manager cookiesForURL: URL1] isEqual: + [OFArray arrayWithObject: cookie1]] && + [[manager cookiesForURL: URL4] isEqual: [OFArray array]]) + + cookie3 = [OFHTTPCookie cookieWithName: @"test" + value: @"3" + domain: @"nil.im"]; + cookie3.secure = true; TEST(@"-[addCookie:forURL:] #3", - R([manager addCookie: cookie[2] forURL: URL[1]])) + R([manager addCookie: cookie3 forURL: URL2])) TEST(@"-[cookiesForURL:] #3", - [[manager cookiesForURL: URL[1]] isEqual: - [OFArray arrayWithObject: cookie[2]]] && - [[manager cookiesForURL: URL[0]] isEqual: [OFArray array]]) - - cookie[2].expires = [OFDate dateWithTimeIntervalSinceNow: -1]; - cookie[3] = [OFHTTPCookie cookieWithName: @"test" - value: @"4" - domain: @"nil.im"]; - cookie[3].domain = @".nil.im"; + [[manager cookiesForURL: URL2] isEqual: + [OFArray arrayWithObject: cookie3]] && + [[manager cookiesForURL: URL1] isEqual: [OFArray array]]) + + cookie3.expires = [OFDate dateWithTimeIntervalSinceNow: -1]; + cookie4 = [OFHTTPCookie cookieWithName: @"test" + value: @"4" + domain: @"nil.im"]; + cookie4.domain = @".nil.im"; TEST(@"-[addCookie:forURL:] #4", - R([manager addCookie: cookie[3] forURL: URL[1]])) + R([manager addCookie: cookie4 forURL: URL2])) TEST(@"-[cookiesForURL:] #4", - [[manager cookiesForURL: URL[1]] isEqual: - [OFArray arrayWithObject: cookie[3]]] && - [[manager cookiesForURL: URL[2]] isEqual: - [OFArray arrayWithObject: cookie[3]]]) - - cookie[4] = [OFHTTPCookie cookieWithName: @"bar" - value: @"5" - domain: @"test.nil.im"]; - TEST(@"-[addCookie:forURL:] #5", - R([manager addCookie: cookie[4] forURL: URL[0]])) + [[manager cookiesForURL: URL2] isEqual: + [OFArray arrayWithObject: cookie4]] && + [[manager cookiesForURL: URL3] isEqual: + [OFArray arrayWithObject: cookie4]]) + + cookie5 = [OFHTTPCookie cookieWithName: @"bar" + value: @"5" + domain: @"test.nil.im"]; + TEST(@"-[addCookie:forURL:] #5", + R([manager addCookie: cookie5 forURL: URL1])) TEST(@"-[cookiesForURL:] #5", - [[manager cookiesForURL: URL[0]] isEqual: - [OFArray arrayWithObject: cookie[3]]] && - [[manager cookiesForURL: URL[2]] isEqual: - [OFArray arrayWithObjects: cookie[3], cookie[4], nil]]) + [[manager cookiesForURL: URL1] isEqual: + [OFArray arrayWithObject: cookie4]] && + [[manager cookiesForURL: URL3] isEqual: + [OFArray arrayWithObjects: cookie4, cookie5, nil]]) TEST(@"-[purgeExpiredCookies]", [manager.cookies isEqual: - [OFArray arrayWithObjects: cookie[2], cookie[3], cookie[4], nil]] && + [OFArray arrayWithObjects: cookie3, cookie4, cookie5, nil]] && R([manager purgeExpiredCookies]) && [manager.cookies isEqual: - [OFArray arrayWithObjects: cookie[3], cookie[4], nil]]) + [OFArray arrayWithObjects: cookie4, cookie5, nil]]) objc_autoreleasePoolPop(pool); } @end Index: tests/OFHTTPCookieTests.m ================================================================== --- tests/OFHTTPCookieTests.m +++ tests/OFHTTPCookieTests.m @@ -15,59 +15,59 @@ #include "config.h" #import "TestsAppDelegate.h" -static OFString *module = @"OFHTTPCookie"; +static OFString *const module = @"OFHTTPCookie"; @implementation TestsAppDelegate (OFHTTPCookieTests) - (void)HTTPCookieTests { void *pool = objc_autoreleasePoolPush(); OFURL *URL = [OFURL URLWithString: @"http://nil.im"]; - OFHTTPCookie *cookie[2]; + OFHTTPCookie *cookie1, *cookie2; OFArray OF_GENERIC(OFHTTPCookie *) *cookies; - cookie[0] = [OFHTTPCookie cookieWithName: @"foo" - value: @"bar" - domain: @"nil.im"]; + cookie1 = [OFHTTPCookie cookieWithName: @"foo" + value: @"bar" + domain: @"nil.im"]; TEST(@"+[cookiesWithResponseHeaderFields:forURL:] #1", [[OFHTTPCookie cookiesWithResponseHeaderFields: [OFDictionary dictionaryWithObject: @"foo=bar" forKey: @"Set-Cookie"] forURL: URL] - isEqual: [OFArray arrayWithObject: cookie[0]]]) + isEqual: [OFArray arrayWithObject: cookie1]]) - cookie[1] = [OFHTTPCookie cookieWithName: @"qux" - value: @"cookie" - domain: @"nil.im"]; + cookie2 = [OFHTTPCookie cookieWithName: @"qux" + value: @"cookie" + domain: @"nil.im"]; TEST(@"+[cookiesWithResponseHeaderFields:forURL:] #2", [[OFHTTPCookie cookiesWithResponseHeaderFields: [OFDictionary dictionaryWithObject: @"foo=bar,qux=cookie" forKey: @"Set-Cookie"] forURL: URL] - isEqual: [OFArray arrayWithObjects: cookie[0], cookie[1], nil]]) - - cookie[0].expires = [OFDate dateWithTimeIntervalSince1970: 1234567890]; - cookie[1].expires = [OFDate dateWithTimeIntervalSince1970: 1234567890]; - cookie[0].path = @"/x"; - cookie[1].domain = @"webkeks.org"; - cookie[1].path = @"/objfw"; - cookie[1].secure = true; - cookie[1].HTTPOnly = true; - [cookie[1].extensions addObject: @"foo"]; - [cookie[1].extensions addObject: @"bar"]; + isEqual: [OFArray arrayWithObjects: cookie1, cookie2, nil]]) + + cookie1.expires = [OFDate dateWithTimeIntervalSince1970: 1234567890]; + cookie2.expires = [OFDate dateWithTimeIntervalSince1970: 1234567890]; + cookie1.path = @"/x"; + cookie2.domain = @"webkeks.org"; + cookie2.path = @"/objfw"; + cookie2.secure = true; + cookie2.HTTPOnly = true; + [cookie2.extensions addObject: @"foo"]; + [cookie2.extensions addObject: @"bar"]; TEST(@"+[cookiesWithResponseHeaderFields:forURL:] #3", [(cookies = [OFHTTPCookie cookiesWithResponseHeaderFields: [OFDictionary dictionaryWithObject: @"foo=bar; Expires=Fri, 13 Feb 2009 23:31:30 GMT; Path=/x," @"qux=cookie; Expires=Fri, 13 Feb 2009 23:31:30 GMT; " @"Domain=webkeks.org; Path=/objfw; Secure; HTTPOnly; foo; bar" forKey: @"Set-Cookie"] forURL: URL]) isEqual: - [OFArray arrayWithObjects: cookie[0], cookie[1], nil]]) + [OFArray arrayWithObjects: cookie1, cookie2, nil]]) TEST(@"+[requestHeaderFieldsWithCookies:]", [[OFHTTPCookie requestHeaderFieldsWithCookies: cookies] isEqual: [OFDictionary dictionaryWithObject: @"foo=bar; qux=cookie" forKey: @"Cookie"]]) objc_autoreleasePoolPop(pool); } @end Index: tests/OFINIFileTests.m ================================================================== --- tests/OFINIFileTests.m +++ tests/OFINIFileTests.m @@ -15,11 +15,11 @@ #include "config.h" #import "TestsAppDelegate.h" -static OFString *module = @"OFINIFile"; +static OFString *module; @implementation TestsAppDelegate (OFINIFileTests) - (void)INIFileTests { void *pool = objc_autoreleasePoolPush(); @@ -47,10 +47,12 @@ OFINICategory *tests, *foobar, *types; OFArray *array; #ifndef OF_NINTENDO_DS OFString *writePath; #endif + + module = @"OFINIFile"; TEST(@"+[fileWithPath:encoding:]", (file = [OFINIFile fileWithPath: @"testfile.ini" encoding: OFStringEncodingCodepage437])) @@ -110,27 +112,21 @@ module = @"OFINIFile"; /* FIXME: Find a way to write files on Nintendo DS */ #ifndef OF_NINTENDO_DS -# ifndef OF_IOS - writePath = @"tmpfile.ini"; -# else - writePath = [OFString pathWithComponents: [OFArray arrayWithObjects: - [[OFApplication environment] objectForKey: @"HOME"], - @"tmp", @"tmpfile.ini", nil]]; -# endif + writePath = [[OFSystemInfo temporaryDirectoryPath] + stringByAppendingPathComponent: @"objfw-tests.ini"]; TEST(@"-[writeToFile:encoding:]", R([file writeToFile: writePath encoding: OFStringEncodingCodepage437]) && - [[OFString - stringWithContentsOfFile: writePath - encoding: OFStringEncodingCodepage437] + [[OFString stringWithContentsOfFile: writePath + encoding: OFStringEncodingCodepage437] isEqual: output]) [[OFFileManager defaultManager] removeItemAtPath: writePath]; #else (void)output; #endif objc_autoreleasePoolPop(pool); } @end Index: tests/OFIPXSocketTests.m ================================================================== --- tests/OFIPXSocketTests.m +++ tests/OFIPXSocketTests.m @@ -17,11 +17,11 @@ #include #import "TestsAppDelegate.h" -static OFString *module = @"OFIPXSocket"; +static OFString *const module = @"OFIPXSocket"; @implementation TestsAppDelegate (OFIPXSocketTests) - (void)IPXSocketTests { void *pool = objc_autoreleasePoolPush(); Index: tests/OFInvocationTests.m ================================================================== --- tests/OFInvocationTests.m +++ tests/OFInvocationTests.m @@ -22,22 +22,22 @@ # include #endif #import "TestsAppDelegate.h" -static OFString *module = @"OFInvocation"; +static OFString *const module = @"OFInvocation"; -struct test_struct { +struct TestStruct { unsigned char c; unsigned int i; }; @implementation TestsAppDelegate (OFInvocationTests) -- (struct test_struct)invocationTestMethod1: (unsigned char)c - : (unsigned int)i - : (struct test_struct *)ptr - : (struct test_struct)st +- (struct TestStruct)invocationTestMethod1: (unsigned char)c + : (unsigned int)i + : (struct TestStruct *)ptr + : (struct TestStruct)st { return st; } - (void)invocationTests @@ -44,11 +44,11 @@ { void *pool = objc_autoreleasePoolPush(); SEL selector = @selector(invocationTestMethod1::::); OFMethodSignature *sig = [self methodSignatureForSelector: selector]; OFInvocation *invocation; - struct test_struct st, st2, *stp = &st, *stp2; + struct TestStruct st, st2, *stp = &st, *stp2; unsigned const char c = 0xAA; unsigned char c2; const unsigned int i = 0x55555555; unsigned int i2; Index: tests/OFJSONTests.m ================================================================== --- tests/OFJSONTests.m +++ tests/OFJSONTests.m @@ -15,42 +15,46 @@ #include "config.h" #import "TestsAppDelegate.h" -static OFString *module = @"OFJSON"; +static OFString *const module = @"OFJSON"; @implementation TestsAppDelegate (JSONTests) - (void)JSONTests { void *pool = objc_autoreleasePoolPush(); - OFString *s = @"{\"foo\"\t:'b\\na\\r', \"x\":/*foo*/ [.5\r,0xF,null" - @"//bar\n,\"foo\",false]}"; - OFDictionary *d = [OFDictionary dictionaryWithKeysAndObjects: + OFString *string = @"{\"foo\"\t:'b\\na\\r', \"x\":/*foo*/ [.5\r,0xF," + @"null//bar\n,\"foo\",false]}"; + OFDictionary *dict = [OFDictionary dictionaryWithKeysAndObjects: @"foo", @"b\na\r", @"x", [OFArray arrayWithObjects: - [OFNumber numberWithFloat: .5f], - [OFNumber numberWithInt: 0xF], - [OFNull null], - @"foo", - [OFNumber numberWithBool: false], - nil], + [OFNumber numberWithFloat: .5f], + [OFNumber numberWithInt: 0xF], + [OFNull null], + @"foo", + [OFNumber numberWithBool: false], + nil], nil]; - TEST(@"-[objectByParsingJSON] #1", [s.objectByParsingJSON isEqual: d]) + TEST(@"-[objectByParsingJSON] #1", + [string.objectByParsingJSON isEqual: dict]) - TEST(@"-[JSONRepresentation]", [[d JSONRepresentation] isEqual: + TEST(@"-[JSONRepresentation]", + [[dict JSONRepresentation] isEqual: @"{\"x\":[0.5,15,null,\"foo\",false],\"foo\":\"b\\na\\r\"}"]) TEST(@"OFJSONRepresentationOptionPretty", - [[d JSONRepresentationWithOptions: OFJSONRepresentationOptionPretty] - isEqual: @"{\n\t\"x\": [\n\t\t0.5,\n\t\t15,\n\t\tnull,\n\t\t" - @"\"foo\",\n\t\tfalse\n\t],\n\t\"foo\": \"b\\na\\r\"\n}"]) + [[dict JSONRepresentationWithOptions: + OFJSONRepresentationOptionPretty] isEqual: + @"{\n\t\"x\": [\n\t\t0.5,\n\t\t15,\n\t\tnull,\n\t\t" + @"\"foo\",\n\t\tfalse\n\t],\n\t\"foo\": \"b\\na\\r\"\n}"]) TEST(@"OFJSONRepresentationOptionJSON5", - [[d JSONRepresentationWithOptions: OFJSONRepresentationOptionJSON5] - isEqual: @"{x:[0.5,15,null,\"foo\",false],foo:\"b\\\na\\r\"}"]) + [[dict JSONRepresentationWithOptions: + OFJSONRepresentationOptionJSON5] isEqual: + @"{x:[0.5,15,null,\"foo\",false],foo:\"b\\\na\\r\"}"]) EXPECT_EXCEPTION(@"-[objectByParsingJSON] #2", OFInvalidJSONException, [@"{" objectByParsingJSON]) EXPECT_EXCEPTION(@"-[objectByParsingJSON] #3", OFInvalidJSONException, [@"]" objectByParsingJSON]) Index: tests/OFKernelEventObserverTests.m ================================================================== --- tests/OFKernelEventObserverTests.m +++ tests/OFKernelEventObserverTests.m @@ -28,11 +28,11 @@ # import "OFSelectKernelEventObserver.h" #endif #import "TestsAppDelegate.h" -#define EXPECTED_EVENTS 3 +static const size_t numExpectedEvents = 3; static OFString *module; @interface ObserverTest: OFObject { @@ -88,11 +88,11 @@ [_testsAppDelegate outputTesting: @"-[observe] with listening socket" inModule: module]; deadline = [OFDate dateWithTimeIntervalSinceNow: 1]; - while (_events < EXPECTED_EVENTS) { + while (_events < numExpectedEvents) { if (deadline.timeIntervalSinceNow < 0) { deadlineExceeded = true; break; } @@ -108,11 +108,11 @@ outputFailure: @"-[observe] not exceeding deadline" inModule: module]; _fails++; } - if (_events == EXPECTED_EVENTS) + if (_events == numExpectedEvents) [_testsAppDelegate outputSuccess: @"-[observe] handling all events" inModule: module]; else { [_testsAppDelegate @@ -122,11 +122,11 @@ } } - (void)objectIsReadyForReading: (id)object { - char buf; + char buffer; switch (_events++) { case 0: if (object == _server) [_testsAppDelegate @@ -147,11 +147,12 @@ inModule: module]; break; case 1: if (object == _accepted && - [object readIntoBuffer: &buf length: 1] == 1 && buf == '0') + [object readIntoBuffer: &buffer length: 1] == 1 && + buffer == '0') [_testsAppDelegate outputSuccess: @"-[observe] with data ready to read" inModule: module]; else { [_testsAppDelegate @@ -167,11 +168,11 @@ inModule: module]; break; case 2: if (object == _accepted && - [object readIntoBuffer: &buf length: 1] == 0) + [object readIntoBuffer: &buffer length: 1] == 0) [_testsAppDelegate outputSuccess: @"-[observe] with closed connection" inModule: module]; else { [_testsAppDelegate Index: tests/OFListTests.m ================================================================== --- tests/OFListTests.m +++ tests/OFListTests.m @@ -15,11 +15,11 @@ #include "config.h" #import "TestsAppDelegate.h" -static OFString *module = @"OFList"; +static OFString *const module = @"OFList"; static OFString *strings[] = { @"Foo", @"Bar", @"Baz" }; @@ -29,11 +29,11 @@ { void *pool = objc_autoreleasePoolPush(); OFList *list; OFEnumerator *enumerator; OFListItem iter; - OFString *obj; + OFString *object; size_t i; bool ok; TEST(@"+[list]", (list = [OFList list])) @@ -95,12 +95,12 @@ TEST(@"-[objectEnumerator]", (enumerator = [list objectEnumerator])) iter = list.firstListItem; i = 0; ok = true; - while ((obj = [enumerator nextObject]) != nil) { - if (![obj isEqual: OFListItemObject(iter)]) + while ((object = [enumerator nextObject]) != nil) { + if (![object isEqual: OFListItemObject(iter)]) ok = false; iter = OFListItemNext(iter); i++; } @@ -119,12 +119,12 @@ iter = list.firstListItem; i = 0; ok = true; - for (OFString *object in list) { - if (![object isEqual: OFListItemObject(iter)]) + for (OFString *object_ in list) { + if (![object_ isEqual: OFListItemObject(iter)]) ok = false; iter = OFListItemNext(iter); i++; } @@ -134,12 +134,12 @@ TEST(@"Fast Enumeration", ok) ok = false; @try { - for (OFString *object in list) { - (void)object; + for (OFString *object_ in list) { + (void)object_; [list removeListItem: list.lastListItem]; } } @catch (OFEnumerationMutationException *e) { ok = true; Index: tests/OFMD5HashTests.m ================================================================== --- tests/OFMD5HashTests.m +++ tests/OFMD5HashTests.m @@ -17,40 +17,40 @@ #include #import "TestsAppDelegate.h" -static OFString *module = @"OFMD5Hash"; +static OFString *const module = @"OFMD5Hash"; -const uint8_t testfile_md5[16] = - "\x00\x8B\x9D\x1B\x58\xDF\xF8\xFE\xEE\xF3\xAE\x8D\xBB\x68\x2D\x38"; +const uint8_t testFileMD5[16] = + "\x00\x8B\x9D\x1B\x58\xDF\xF8\xFE\xEE\xF3\xAE\x8D\xBB\x68\x2D\x38"; @implementation TestsAppDelegate (OFMD5HashTests) - (void)MD5HashTests { void *pool = objc_autoreleasePoolPush(); - OFMD5Hash *md5, *copy; - OFFile *f = [OFFile fileWithPath: @"testfile.bin" mode: @"r"]; + OFMD5Hash *MD5, *MD5Copy; + OFFile *file = [OFFile fileWithPath: @"testfile.bin" mode: @"r"]; TEST(@"+[hashWithAllowsSwappableMemory:]", - (md5 = [OFMD5Hash hashWithAllowsSwappableMemory: true])) - - while (!f.atEndOfStream) { - char buf[64]; - size_t len = [f readIntoBuffer: buf length: 64]; - [md5 updateWithBuffer: buf length: len]; - } - [f close]; - - TEST(@"-[copy]", (copy = [[md5 copy] autorelease])) + (MD5 = [OFMD5Hash hashWithAllowsSwappableMemory: true])) + + while (!file.atEndOfStream) { + char buffer[64]; + size_t length = [file readIntoBuffer: buffer length: 64]; + [MD5 updateWithBuffer: buffer length: length]; + } + [file close]; + + TEST(@"-[copy]", (MD5Copy = [[MD5 copy] autorelease])) TEST(@"-[digest]", - memcmp(md5.digest, testfile_md5, 16) == 0 && - memcmp(copy.digest, testfile_md5, 16) == 0) + memcmp(MD5.digest, testFileMD5, 16) == 0 && + memcmp(MD5Copy.digest, testFileMD5, 16) == 0) EXPECT_EXCEPTION(@"Detect invalid call of " @"-[updateWithBuffer:length]", OFHashAlreadyCalculatedException, - [md5 updateWithBuffer: "" length: 1]) + [MD5 updateWithBuffer: "" length: 1]) objc_autoreleasePoolPop(pool); } @end Index: tests/OFMethodSignatureTests.m ================================================================== --- tests/OFMethodSignatureTests.m +++ tests/OFMethodSignatureTests.m @@ -21,19 +21,19 @@ # include #endif #import "TestsAppDelegate.h" -static OFString *module = @"OFMethodSignature"; +static OFString *const module = @"OFMethodSignature"; -struct test1_struct { +struct Test1Struct { char c; int i; char d; }; -struct test2_struct { +struct Test2Struct { char c; struct { short s; int i; } st; @@ -43,23 +43,23 @@ } u; double d; }; #if !defined(__STDC_NO_COMPLEX__) && defined(HAVE_COMPLEX_H) -struct test3_struct { +struct Test3Struct { char c; complex double cd; }; #endif -union test3_union { +union Test3Union { char c; int i; double d; }; -union test4_union { +union Test4Union { char c; struct { short x, y; } st; int i; @@ -71,38 +71,42 @@ @implementation TestsAppDelegate (OFMethodSignatureTests) - (void)methodSignatureTests { void *pool = objc_autoreleasePoolPush(); - OFMethodSignature *ms; + OFMethodSignature *methodSignature; TEST(@"-[signatureWithObjCTypes:] #1", - (ms = [OFMethodSignature signatureWithObjCTypes: - "i28@0:8S16*20"]) && ms.numberOfArguments == 4 && - strcmp(ms.methodReturnType, "i") == 0 && - strcmp([ms argumentTypeAtIndex: 0], "@") == 0 && - strcmp([ms argumentTypeAtIndex: 1], ":") == 0 && - strcmp([ms argumentTypeAtIndex: 2], "S") == 0 && - strcmp([ms argumentTypeAtIndex: 3], "*") == 0 && - ms.frameLength == 28 && [ms argumentOffsetAtIndex: 0] == 0 && - [ms argumentOffsetAtIndex: 1] == 8 && - [ms argumentOffsetAtIndex: 2] == 16 && - [ms argumentOffsetAtIndex: 3] == 20) + (methodSignature = [OFMethodSignature signatureWithObjCTypes: + "i28@0:8S16*20"]) && + methodSignature.numberOfArguments == 4 && + strcmp(methodSignature.methodReturnType, "i") == 0 && + strcmp([methodSignature argumentTypeAtIndex: 0], "@") == 0 && + strcmp([methodSignature argumentTypeAtIndex: 1], ":") == 0 && + strcmp([methodSignature argumentTypeAtIndex: 2], "S") == 0 && + strcmp([methodSignature argumentTypeAtIndex: 3], "*") == 0 && + methodSignature.frameLength == 28 && + [methodSignature argumentOffsetAtIndex: 0] == 0 && + [methodSignature argumentOffsetAtIndex: 1] == 8 && + [methodSignature argumentOffsetAtIndex: 2] == 16 && + [methodSignature argumentOffsetAtIndex: 3] == 20) TEST(@"-[signatureWithObjCTypes:] #2", - (ms = [OFMethodSignature signatureWithObjCTypes: + (methodSignature = [OFMethodSignature signatureWithObjCTypes: "{s0=csi(u1={s2=iii{s3=(u4=ic^v*)}})}24@0:8" "^{s0=csi(u1={s2=iii{s3=(u4=ic^v*)}})}16"]) && - ms.numberOfArguments == 3 && strcmp(ms.methodReturnType, + methodSignature.numberOfArguments == 3 && + strcmp(methodSignature.methodReturnType, "{s0=csi(u1={s2=iii{s3=(u4=ic^v*)}})}") == 0 && - strcmp([ms argumentTypeAtIndex: 0], "@") == 0 && - strcmp([ms argumentTypeAtIndex: 1], ":") == 0 && - strcmp([ms argumentTypeAtIndex: 2], + strcmp([methodSignature argumentTypeAtIndex: 0], "@") == 0 && + strcmp([methodSignature argumentTypeAtIndex: 1], ":") == 0 && + strcmp([methodSignature argumentTypeAtIndex: 2], "^{s0=csi(u1={s2=iii{s3=(u4=ic^v*)}})}") == 0 && - ms.frameLength == 24 && [ms argumentOffsetAtIndex: 0] == 0 && - [ms argumentOffsetAtIndex: 1] == 8 && - [ms argumentOffsetAtIndex: 2] == 16) + methodSignature.frameLength == 24 && + [methodSignature argumentOffsetAtIndex: 0] == 0 && + [methodSignature argumentOffsetAtIndex: 1] == 8 && + [methodSignature argumentOffsetAtIndex: 2] == 16) EXPECT_EXCEPTION(@"-[signatureWithObjCTypes:] #3", OFInvalidFormatException, [OFMethodSignature signatureWithObjCTypes: "{ii"]) @@ -117,61 +121,61 @@ EXPECT_EXCEPTION(@"-[signatureWithObjCTypes:] #6", OFInvalidFormatException, [OFMethodSignature signatureWithObjCTypes: "{{}0"]) TEST(@"OFSizeOfTypeEncoding() #1", - OFSizeOfTypeEncoding(@encode(struct test1_struct)) == - sizeof(struct test1_struct)) + OFSizeOfTypeEncoding(@encode(struct Test1Struct)) == + sizeof(struct Test1Struct)) TEST(@"OFSizeOfTypeEncoding() #2", - OFSizeOfTypeEncoding(@encode(struct test2_struct)) == - sizeof(struct test2_struct)) + OFSizeOfTypeEncoding(@encode(struct Test2Struct)) == + sizeof(struct Test2Struct)) #if !defined(__STDC_NO_COMPLEX__) && defined(HAVE_COMPLEX_H) && \ OF_GCC_VERSION >= 402 TEST(@"OFSizeOfTypeEncoding() #3", - OFSizeOfTypeEncoding(@encode(struct test3_struct)) == - sizeof(struct test3_struct)) + OFSizeOfTypeEncoding(@encode(struct Test3Struct)) == + sizeof(struct Test3Struct)) #endif TEST(@"OFSizeOfTypeEncoding() #4", - OFSizeOfTypeEncoding(@encode(union test3_union)) == - sizeof(union test3_union)) + OFSizeOfTypeEncoding(@encode(union Test3Union)) == + sizeof(union Test3Union)) TEST(@"OFSizeOfTypeEncoding() #5", - OFSizeOfTypeEncoding(@encode(union test4_union)) == - sizeof(union test4_union)) + OFSizeOfTypeEncoding(@encode(union Test4Union)) == + sizeof(union Test4Union)) TEST(@"OFSizeOfTypeEncoding() #6", - OFSizeOfTypeEncoding(@encode(struct test1_struct [5])) == - sizeof(struct test1_struct [5])) + OFSizeOfTypeEncoding(@encode(struct Test1Struct [5])) == + sizeof(struct Test1Struct [5])) TEST(@"OFAlignmentOfTypeEncoding() #1", - OFAlignmentOfTypeEncoding(@encode(struct test1_struct)) == - OF_ALIGNOF(struct test1_struct)) + OFAlignmentOfTypeEncoding(@encode(struct Test1Struct)) == + OF_ALIGNOF(struct Test1Struct)) TEST(@"OFAlignmentOfTypeEncoding() #2", - OFAlignmentOfTypeEncoding(@encode(struct test2_struct)) == - OF_ALIGNOF(struct test2_struct)) + OFAlignmentOfTypeEncoding(@encode(struct Test2Struct)) == + OF_ALIGNOF(struct Test2Struct)) #if !defined(__STDC_NO_COMPLEX__) && defined(HAVE_COMPLEX_H) && \ OF_GCC_VERSION >= 402 TEST(@"OFAlignmentOfTypeEncoding() #3", - OFAlignmentOfTypeEncoding(@encode(struct test3_struct)) == - OF_ALIGNOF(struct test3_struct)) + OFAlignmentOfTypeEncoding(@encode(struct Test3Struct)) == + OF_ALIGNOF(struct Test3Struct)) #endif TEST(@"OFAlignmentOfTypeEncoding() #4", - OFAlignmentOfTypeEncoding(@encode(union test3_union)) == - OF_ALIGNOF(union test3_union)) + OFAlignmentOfTypeEncoding(@encode(union Test3Union)) == + OF_ALIGNOF(union Test3Union)) TEST(@"OFAlignmentOfTypeEncoding() #5", - OFAlignmentOfTypeEncoding(@encode(union test4_union)) == - OF_ALIGNOF(union test4_union)) + OFAlignmentOfTypeEncoding(@encode(union Test4Union)) == + OF_ALIGNOF(union Test4Union)) TEST(@"OFAlignmentOfTypeEncoding() #6", - OFAlignmentOfTypeEncoding(@encode(struct test1_struct [5])) == - OF_ALIGNOF(struct test1_struct [5])) + OFAlignmentOfTypeEncoding(@encode(struct Test1Struct [5])) == + OF_ALIGNOF(struct Test1Struct [5])) objc_autoreleasePoolPop(pool); } @end Index: tests/OFNumberTests.m ================================================================== --- tests/OFNumberTests.m +++ tests/OFNumberTests.m @@ -15,78 +15,78 @@ #include "config.h" #import "TestsAppDelegate.h" -static OFString *module = @"OFNumber"; +static OFString *const module = @"OFNumber"; @implementation TestsAppDelegate (OFNumberTests) - (void)numberTests { void *pool = objc_autoreleasePoolPush(); - OFNumber *num; + OFNumber *number; TEST(@"+[numberWithLongLong:]", - (num = [OFNumber numberWithLongLong: 123456789])) + (number = [OFNumber numberWithLongLong: 123456789])) TEST(@"-[isEqual:]", - [num isEqual: [OFNumber numberWithLong: 123456789]]) + [number isEqual: [OFNumber numberWithLong: 123456789]]) + + TEST(@"-[hash]", number.hash == 0x82D8BC42) - TEST(@"-[hash]", num.hash == 0x82D8BC42) + TEST(@"-[charValue]", number.charValue == 21) - TEST(@"-[charValue]", num.charValue == 21) - - TEST(@"-[doubleValue]", num.doubleValue == 123456789.L) + TEST(@"-[doubleValue]", number.doubleValue == 123456789.L) TEST(@"signed char minimum & maximum unmodified", - (num = [OFNumber numberWithChar: SCHAR_MIN]) && - num.charValue == SCHAR_MIN && - (num = [OFNumber numberWithChar: SCHAR_MAX]) && - num.charValue == SCHAR_MAX) + (number = [OFNumber numberWithChar: SCHAR_MIN]) && + number.charValue == SCHAR_MIN && + (number = [OFNumber numberWithChar: SCHAR_MAX]) && + number.charValue == SCHAR_MAX) TEST(@"short minimum & maximum unmodified", - (num = [OFNumber numberWithShort: SHRT_MIN]) && - num.shortValue == SHRT_MIN && - (num = [OFNumber numberWithShort: SHRT_MAX]) && - num.shortValue == SHRT_MAX) + (number = [OFNumber numberWithShort: SHRT_MIN]) && + number.shortValue == SHRT_MIN && + (number = [OFNumber numberWithShort: SHRT_MAX]) && + number.shortValue == SHRT_MAX) TEST(@"int minimum & maximum unmodified", - (num = [OFNumber numberWithInt: INT_MIN]) && - num.intValue == INT_MIN && - (num = [OFNumber numberWithInt: INT_MAX]) && - num.intValue == INT_MAX) + (number = [OFNumber numberWithInt: INT_MIN]) && + number.intValue == INT_MIN && + (number = [OFNumber numberWithInt: INT_MAX]) && + number.intValue == INT_MAX) TEST(@"long minimum & maximum unmodified", - (num = [OFNumber numberWithLong: LONG_MIN]) && - num.longValue == LONG_MIN && - (num = [OFNumber numberWithLong: LONG_MAX]) && - num.longValue == LONG_MAX) + (number = [OFNumber numberWithLong: LONG_MIN]) && + number.longValue == LONG_MIN && + (number = [OFNumber numberWithLong: LONG_MAX]) && + number.longValue == LONG_MAX) TEST(@"long long minimum & maximum unmodified", - (num = [OFNumber numberWithLongLong: LLONG_MIN]) && - num.longLongValue == LLONG_MIN && - (num = [OFNumber numberWithLongLong: LLONG_MAX]) && - num.longLongValue == LLONG_MAX) + (number = [OFNumber numberWithLongLong: LLONG_MIN]) && + number.longLongValue == LLONG_MIN && + (number = [OFNumber numberWithLongLong: LLONG_MAX]) && + number.longLongValue == LLONG_MAX) TEST(@"unsigned char maximum unmodified", - (num = [OFNumber numberWithUnsignedChar: UCHAR_MAX]) && - num.unsignedCharValue == UCHAR_MAX) + (number = [OFNumber numberWithUnsignedChar: UCHAR_MAX]) && + number.unsignedCharValue == UCHAR_MAX) TEST(@"unsigned short maximum unmodified", - (num = [OFNumber numberWithUnsignedShort: USHRT_MAX]) && - num.unsignedShortValue == USHRT_MAX) + (number = [OFNumber numberWithUnsignedShort: USHRT_MAX]) && + number.unsignedShortValue == USHRT_MAX) TEST(@"unsigned int maximum unmodified", - (num = [OFNumber numberWithUnsignedInt: UINT_MAX]) && - num.unsignedIntValue == UINT_MAX) + (number = [OFNumber numberWithUnsignedInt: UINT_MAX]) && + number.unsignedIntValue == UINT_MAX) TEST(@"unsigned long maximum unmodified", - (num = [OFNumber numberWithUnsignedLong: ULONG_MAX]) && - num.unsignedLongValue == ULONG_MAX) + (number = [OFNumber numberWithUnsignedLong: ULONG_MAX]) && + number.unsignedLongValue == ULONG_MAX) TEST(@"unsigned long long maximum unmodified", - (num = [OFNumber numberWithUnsignedLongLong: ULLONG_MAX]) && - num.unsignedLongLongValue == ULLONG_MAX) + (number = [OFNumber numberWithUnsignedLongLong: ULLONG_MAX]) && + number.unsignedLongLongValue == ULLONG_MAX) objc_autoreleasePoolPop(pool); } @end Index: tests/OFObjectTests.m ================================================================== --- tests/OFObjectTests.m +++ tests/OFObjectTests.m @@ -21,13 +21,13 @@ # define TOO_BIG (SIZE_MAX / 3) #else # define TOO_BIG (SIZE_MAX - 128) #endif -static OFString *module = @"OFObject"; +static OFString *const module = @"OFObject"; -@interface MyObj: OFObject +@interface MyObject: OFObject { id _objectValue; Class _classValue; bool _boolValue; char _charValue; @@ -59,11 +59,11 @@ @property (nonatomic) unsigned long long unsignedLongLongValue; @property (nonatomic) float floatValue; @property (nonatomic) double doubleValue; @end -@implementation MyObj +@implementation MyObject @synthesize objectValue = _objectValue, classValue = _classValue; @synthesize boolValue = _boolValue, charValue = _charValue; @synthesize shortValue = _shortValue, intValue = _intValue; @synthesize longValue = _longValue, longLongValue = _longLongValue; @synthesize unsignedCharValue = _unsignedCharValue; @@ -83,134 +83,139 @@ @implementation TestsAppDelegate (OFObjectTests) - (void)objectTests { void *pool = objc_autoreleasePoolPush(); - OFObject *o; - MyObj *m; + OFObject *object; + MyObject *myObject; TEST(@"+[description]", [[OFObject description] isEqual: @"OFObject"] && - [[MyObj description] isEqual: @"MyObj"]) + [[MyObject description] isEqual: @"MyObject"]) - o = [[[OFObject alloc] init] autorelease]; - m = [[[MyObj alloc] init] autorelease]; + object = [[[OFObject alloc] init] autorelease]; + myObject = [[[MyObject alloc] init] autorelease]; TEST(@"-[description]", - [o.description isEqual: @""] && - [m.description isEqual: @""]) + [object.description isEqual: @""] && + [myObject.description isEqual: @""]) - m.objectValue = @"Hello"; - m.classValue = [m class]; + myObject.objectValue = @"Hello"; + myObject.classValue = myObject.class; TEST(@"-[valueForKey:]", - [[m valueForKey: @"objectValue"] isEqual: @"Hello"] && - [[m valueForKey: @"classValue"] isEqual: m.class] && - [[m valueForKey: @"class"] isEqual: m.class]) + [[myObject valueForKey: @"objectValue"] isEqual: @"Hello"] && + [[myObject valueForKey: @"classValue"] isEqual: myObject.class] && + [[myObject valueForKey: @"class"] isEqual: myObject.class]) EXPECT_EXCEPTION(@"-[valueForKey:] with undefined key", - OFUndefinedKeyException, [m valueForKey: @"undefined"]) + OFUndefinedKeyException, [myObject valueForKey: @"undefined"]) TEST(@"-[setValue:forKey:]", - R([m setValue: @"World" forKey: @"objectValue"]) && - R([m setValue: [OFObject class] forKey: @"classValue"]) && - [m.objectValue isEqual: @"World"] && - [m.classValue isEqual: [OFObject class]]) + R([myObject setValue: @"World" forKey: @"objectValue"]) && + R([myObject setValue: [OFObject class] forKey: @"classValue"]) && + [myObject.objectValue isEqual: @"World"] && + [myObject.classValue isEqual: [OFObject class]]) EXPECT_EXCEPTION(@"-[setValue:forKey:] with undefined key", - OFUndefinedKeyException, [m setValue: @"x" forKey: @"undefined"]) - - m.boolValue = 1; - m.charValue = 2; - m.shortValue = 3; - m.intValue = 4; - m.longValue = 5; - m.longLongValue = 6; - m.unsignedCharValue = 7; - m.unsignedShortValue = 8; - m.unsignedIntValue = 9; - m.unsignedLongValue = 10; - m.unsignedLongLongValue = 11; - m.floatValue = 12; - m.doubleValue = 13; + OFUndefinedKeyException, + [myObject setValue: @"x" forKey: @"undefined"]) + + myObject.boolValue = 1; + myObject.charValue = 2; + myObject.shortValue = 3; + myObject.intValue = 4; + myObject.longValue = 5; + myObject.longLongValue = 6; + myObject.unsignedCharValue = 7; + myObject.unsignedShortValue = 8; + myObject.unsignedIntValue = 9; + myObject.unsignedLongValue = 10; + myObject.unsignedLongLongValue = 11; + myObject.floatValue = 12; + myObject.doubleValue = 13; TEST(@"Auto-wrapping of -[valueForKey:]", - [[m valueForKey: @"boolValue"] isEqual: + [[myObject valueForKey: @"boolValue"] isEqual: [OFNumber numberWithBool: 1]] && - [[m valueForKey: @"charValue"] isEqual: + [[myObject valueForKey: @"charValue"] isEqual: [OFNumber numberWithChar: 2]] && - [[m valueForKey: @"shortValue"] isEqual: + [[myObject valueForKey: @"shortValue"] isEqual: [OFNumber numberWithShort: 3]] && - [[m valueForKey: @"intValue"] isEqual: + [[myObject valueForKey: @"intValue"] isEqual: [OFNumber numberWithInt: 4]] && - [[m valueForKey: @"longValue"] isEqual: + [[myObject valueForKey: @"longValue"] isEqual: [OFNumber numberWithLong: 5]] && - [[m valueForKey: @"longLongValue"] isEqual: + [[myObject valueForKey: @"longLongValue"] isEqual: [OFNumber numberWithLongLong: 6]] && - [[m valueForKey: @"unsignedCharValue"] isEqual: + [[myObject valueForKey: @"unsignedCharValue"] isEqual: [OFNumber numberWithUnsignedChar: 7]] && - [[m valueForKey: @"unsignedShortValue"] isEqual: + [[myObject valueForKey: @"unsignedShortValue"] isEqual: [OFNumber numberWithUnsignedShort: 8]] && - [[m valueForKey: @"unsignedIntValue"] isEqual: + [[myObject valueForKey: @"unsignedIntValue"] isEqual: [OFNumber numberWithUnsignedInt: 9]] && - [[m valueForKey: @"unsignedLongValue"] isEqual: + [[myObject valueForKey: @"unsignedLongValue"] isEqual: [OFNumber numberWithUnsignedLong: 10]] && - [[m valueForKey: @"unsignedLongLongValue"] isEqual: + [[myObject valueForKey: @"unsignedLongLongValue"] isEqual: [OFNumber numberWithUnsignedLongLong: 11]] && - [[m valueForKey: @"floatValue"] isEqual: + [[myObject valueForKey: @"floatValue"] isEqual: [OFNumber numberWithFloat: 12]] && - [[m valueForKey: @"doubleValue"] isEqual: + [[myObject valueForKey: @"doubleValue"] isEqual: [OFNumber numberWithDouble: 13]]) TEST(@"Auto-wrapping of -[setValue:forKey:]", - R([m setValue: [OFNumber numberWithBool: 0] - forKey: @"boolValue"]) && - R([m setValue: [OFNumber numberWithChar: 10] - forKey: @"charValue"]) && - R([m setValue: [OFNumber numberWithShort: 20] - forKey: @"shortValue"]) && - R([m setValue: [OFNumber numberWithInt: 30] - forKey: @"intValue"]) && - R([m setValue: [OFNumber numberWithLong: 40] - forKey: @"longValue"]) && - R([m setValue: [OFNumber numberWithLongLong: 50] - forKey: @"longLongValue"]) && - R([m setValue: [OFNumber numberWithUnsignedChar: 60] - forKey: @"unsignedCharValue"]) && - R([m setValue: [OFNumber numberWithUnsignedShort: 70] - forKey: @"unsignedShortValue"]) && - R([m setValue: [OFNumber numberWithUnsignedInt: 80] - forKey: @"unsignedIntValue"]) && - R([m setValue: [OFNumber numberWithUnsignedLong: 90] - forKey: @"unsignedLongValue"]) && - R([m setValue: [OFNumber numberWithUnsignedLongLong: 100] - forKey: @"unsignedLongLongValue"]) && - R([m setValue: [OFNumber numberWithFloat: 110] - forKey: @"floatValue"]) && - R([m setValue: [OFNumber numberWithDouble: 120] - forKey: @"doubleValue"]) && - m.isBoolValue == 0 && m.charValue == 10 && m.shortValue == 20 && - m.intValue == 30 && m.longValue == 40 && m.longLongValue == 50 && - m.unsignedCharValue == 60 && m.unsignedShortValue == 70 && - m.unsignedIntValue == 80 && m.unsignedLongValue == 90 && - m.unsignedLongLongValue == 100 && m.floatValue == 110 && - m.doubleValue == 120) + R([myObject setValue: [OFNumber numberWithBool: 0] + forKey: @"boolValue"]) && + R([myObject setValue: [OFNumber numberWithChar: 10] + forKey: @"charValue"]) && + R([myObject setValue: [OFNumber numberWithShort: 20] + forKey: @"shortValue"]) && + R([myObject setValue: [OFNumber numberWithInt: 30] + forKey: @"intValue"]) && + R([myObject setValue: [OFNumber numberWithLong: 40] + forKey: @"longValue"]) && + R([myObject setValue: [OFNumber numberWithLongLong: 50] + forKey: @"longLongValue"]) && + R([myObject setValue: [OFNumber numberWithUnsignedChar: 60] + forKey: @"unsignedCharValue"]) && + R([myObject setValue: [OFNumber numberWithUnsignedShort: 70] + forKey: @"unsignedShortValue"]) && + R([myObject setValue: [OFNumber numberWithUnsignedInt: 80] + forKey: @"unsignedIntValue"]) && + R([myObject setValue: [OFNumber numberWithUnsignedLong: 90] + forKey: @"unsignedLongValue"]) && + R([myObject setValue: [OFNumber numberWithUnsignedLongLong: 100] + forKey: @"unsignedLongLongValue"]) && + R([myObject setValue: [OFNumber numberWithFloat: 110] + forKey: @"floatValue"]) && + R([myObject setValue: [OFNumber numberWithDouble: 120] + forKey: @"doubleValue"]) && + myObject.isBoolValue == 0 && myObject.charValue == 10 && + myObject.shortValue == 20 && myObject.intValue == 30 && + myObject.longValue == 40 && myObject.longLongValue == 50 && + myObject.unsignedCharValue == 60 && + myObject.unsignedShortValue == 70 && + myObject.unsignedIntValue == 80 && + myObject.unsignedLongValue == 90 && + myObject.unsignedLongLongValue == 100 && + myObject.floatValue == 110 && + myObject.doubleValue == 120) EXPECT_EXCEPTION(@"Catch -[setValue:forKey:] with nil key for scalar", - OFInvalidArgumentException, [m setValue: (id _Nonnull)nil - forKey: @"intValue"]) + OFInvalidArgumentException, + [myObject setValue: (id _Nonnull)nil forKey: @"intValue"]) TEST(@"-[valueForKeyPath:]", - (m = [[[MyObj alloc] init] autorelease]) && - (m.objectValue = [[[MyObj alloc] init] autorelease]) && - R([m.objectValue - setObjectValue: [[[MyObj alloc] init] autorelease]]) && - R([[m.objectValue objectValue] setDoubleValue: 0.5]) && - [[m valueForKeyPath: @"objectValue.objectValue.doubleValue"] + (myObject = [[[MyObject alloc] init] autorelease]) && + (myObject.objectValue = [[[MyObject alloc] init] autorelease]) && + R([myObject.objectValue + setObjectValue: [[[MyObject alloc] init] autorelease]]) && + R([[myObject.objectValue objectValue] setDoubleValue: 0.5]) && + [[myObject valueForKeyPath: @"objectValue.objectValue.doubleValue"] doubleValue] == 0.5) TEST(@"[-setValue:forKeyPath:]", - R([m setValue: [OFNumber numberWithDouble: 0.75] - forKeyPath: @"objectValue.objectValue.doubleValue"]) && - [[m.objectValue objectValue] doubleValue] == 0.75) + R([myObject setValue: [OFNumber numberWithDouble: 0.75] + forKeyPath: @"objectValue.objectValue.doubleValue"]) && + [[myObject.objectValue objectValue] doubleValue] == 0.75) objc_autoreleasePoolPop(pool); } @end ADDED tests/OFPBKDF2Tests.m Index: tests/OFPBKDF2Tests.m ================================================================== --- tests/OFPBKDF2Tests.m +++ tests/OFPBKDF2Tests.m @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2008-2021 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#include + +#import "TestsAppDelegate.h" + +static OFString *const module = @"OFPBKDF2"; + +@implementation TestsAppDelegate (OFPBKDF2Tests) +- (void)PBKDF2Tests +{ + void *pool = objc_autoreleasePoolPush(); + OFHMAC *HMAC = [OFHMAC HMACWithHashClass: [OFSHA1Hash class] + allowsSwappableMemory: true]; + unsigned char key[25]; + + /* Test vectors from RFC 6070 */ + + TEST(@"PBKDF2-SHA1, 1 iteration", + R(OFPBKDF2((OFPBKDF2Parameters){ + .HMAC = HMAC, + .iterations = 1, + .salt = (unsigned char *)"salt", + .saltLength = 4, + .password = "password", + .passwordLength = 8, + .key = key, + .keyLength = 20, + .allowsSwappableMemory = true + })) && memcmp(key, "\x0C\x60\xC8\x0F\x96\x1F\x0E\x71\xF3\xA9\xB5" + "\x24\xAF\x60\x12\x06\x2F\xE0\x37\xA6", 20) == 0) + + TEST(@"PBKDF2-SHA1, 2 iterations", + R(OFPBKDF2((OFPBKDF2Parameters){ + .HMAC = HMAC, + .iterations = 2, + .salt = (unsigned char *)"salt", + .saltLength = 4, + .password = "password", + .passwordLength = 8, + .key = key, + .keyLength = 20, + .allowsSwappableMemory = true + })) && memcmp(key, "\xEA\x6C\x01\x4D\xC7\x2D\x6F\x8C\xCD\x1E\xD9" + "\x2A\xCE\x1D\x41\xF0\xD8\xDE\x89\x57", 20) == 0) + + TEST(@"PBKDF2-SHA1, 4096 iterations", + R(OFPBKDF2((OFPBKDF2Parameters){ + .HMAC = HMAC, + .iterations = 4096, + .salt = (unsigned char *)"salt", + .saltLength = 4, + .password = "password", + .passwordLength = 8, + .key = key, + .keyLength = 20, + .allowsSwappableMemory = true + })) && memcmp(key, "\x4B\x00\x79\x01\xB7\x65\x48\x9A\xBE\xAD\x49" + "\xD9\x26\xF7\x21\xD0\x65\xA4\x29\xC1", 20) == 0) + + /* This test takes too long, even on a fast machine. */ +#if 0 + TEST(@"PBKDF2-SHA1, 16777216 iterations", + R(OFPBKDF2((OFPBKDF2Parameters){ + .HMAC = HMAC, + .iterations = 16777216, + .salt = (unsigned char *)"salt", + .saltLength = 4, + .password = "password", + .passwordLength = 8, + .key = key, + .keyLength = 20, + .allowsSwappableMemory = true + })) && memcmp(key, "\xEE\xFE\x3D\x61\xCD\x4D\xA4\xE4\xE9\x94\x5B" + "\x3D\x6B\xA2\x15\x8C\x26\x34\xE9\x84", 20) == 0) +#endif + + TEST(@"PBKDF2-SHA1, 4096 iterations, key > 1 block", + R(OFPBKDF2((OFPBKDF2Parameters){ + .HMAC = HMAC, + .iterations = 4096, + .salt = (unsigned char *)"saltSALTsaltSALTsalt" + "SALTsaltSALTsalt", + .saltLength = 36, + .password = "passwordPASSWORDpassword", + .passwordLength = 24, + .key = key, + .keyLength = 25, + .allowsSwappableMemory = true + })) && + memcmp(key, "\x3D\x2E\xEC\x4F\xE4\x1C\x84\x9B\x80\xC8\xD8\x36\x62" + "\xC0\xE4\x4A\x8B\x29\x1A\x96\x4C\xF2\xF0\x70\x38", 25) == 0) + + TEST(@"PBKDF2-SHA1, 4096 iterations, key < 1 block", + R(OFPBKDF2((OFPBKDF2Parameters){ + .HMAC = HMAC, + .iterations = 4096, + .salt = (unsigned char *)"sa\0lt", + .saltLength = 5, + .password = "pass\0word", + .passwordLength = 9, + .key = key, + .keyLength = 16, + .allowsSwappableMemory = true + })) && memcmp(key, "\x56\xFA\x6A\xA7\x55\x48\x09\x9D\xCC\x37\xD7" + "\xF0\x34\x25\xE0\xC3", 16) == 0) + + objc_autoreleasePoolPop(pool); +} +@end Index: tests/OFPluginTests.m ================================================================== --- tests/OFPluginTests.m +++ tests/OFPluginTests.m @@ -18,26 +18,26 @@ #import "TestsAppDelegate.h" #import "plugin/TestPlugin.h" #ifndef OF_IOS -# define PLUGIN_PATH @"plugin/TestPlugin" +static OFString *const pluginPath = @"plugin/TestPlugin"; #else -# define PLUGIN_PATH @"PlugIns/TestPlugin" +static OFString *const pluginPath = @"PlugIns/TestPlugin"; #endif -static OFString *module = @"OFPlugin"; +static OFString *const module = @"OFPlugin"; @implementation TestsAppDelegate (OFPluginTests) - (void)pluginTests { void *pool = objc_autoreleasePoolPush(); TestPlugin *plugin; TEST(@"+[pluginWithPath:]", - (plugin = [OFPlugin pluginWithPath: PLUGIN_PATH])) + (plugin = [OFPlugin pluginWithPath: pluginPath])) TEST(@"TestPlugin's -[test:]", [plugin test: 1234] == 2468) objc_autoreleasePoolPop(pool); } @end Index: tests/OFPropertyListTests.m ================================================================== --- tests/OFPropertyListTests.m +++ tests/OFPropertyListTests.m @@ -23,23 +23,23 @@ @"\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">" \ @"\n" \ x @"\n" \ @"" -static OFString *module = @"OFPropertyList"; -static OFString *PLIST1 = PLIST(@"Hello"); -static OFString *PLIST2 = PLIST( +static OFString *const module = @"OFPropertyList"; +static OFString *const PLIST1 = PLIST(@"Hello"); +static OFString *const PLIST2 = PLIST( @"" @" Hello" @" V29ybGQh" @" 2018-03-14T12:34:56Z" @" " @" " @" 12.25" @" -10" @""); -static OFString *PLIST3 = PLIST( +static OFString *const PLIST3 = PLIST( @"" @" array" @" " @" Hello" @" V29ybGQh" Index: tests/OFRIPEMD160HashTests.m ================================================================== --- tests/OFRIPEMD160HashTests.m +++ tests/OFRIPEMD160HashTests.m @@ -17,41 +17,41 @@ #include #import "TestsAppDelegate.h" -static OFString *module = @"OFRIPEMD160Hash"; +static OFString *const module = @"OFRIPEMD160Hash"; -const uint8_t testfile_rmd160[20] = +const uint8_t testFileRIPEMD160[20] = "\x46\x02\x97\xF5\x85\xDF\xB9\x21\x00\xC8\xF9\x87\xC6\xEC\x84\x0D\xCE" "\xE6\x08\x8B"; @implementation TestsAppDelegate (OFRIPEMD160HashTests) - (void)RIPEMD160HashTests { void *pool = objc_autoreleasePoolPush(); - OFRIPEMD160Hash *rmd160, *copy; - OFFile *f = [OFFile fileWithPath: @"testfile.bin" mode: @"r"]; + OFRIPEMD160Hash *RIPEMD160, *RIPEMD160Copy; + OFFile *file = [OFFile fileWithPath: @"testfile.bin" mode: @"r"]; TEST(@"+[hashWithAllowsSwappableMemory:]", - (rmd160 = [OFRIPEMD160Hash hashWithAllowsSwappableMemory: true])) - - while (!f.atEndOfStream) { - char buf[64]; - size_t len = [f readIntoBuffer: buf length: 64]; - [rmd160 updateWithBuffer: buf length: len]; - } - [f close]; - - TEST(@"-[copy]", (copy = [[rmd160 copy] autorelease])) + (RIPEMD160 = [OFRIPEMD160Hash hashWithAllowsSwappableMemory: true])) + + while (!file.atEndOfStream) { + char buffer[64]; + size_t length = [file readIntoBuffer: buffer length: 64]; + [RIPEMD160 updateWithBuffer: buffer length: length]; + } + [file close]; + + TEST(@"-[copy]", (RIPEMD160Copy = [[RIPEMD160 copy] autorelease])) TEST(@"-[digest]", - memcmp(rmd160.digest, testfile_rmd160, 20) == 0 && - memcmp(copy.digest, testfile_rmd160, 20) == 0) + memcmp(RIPEMD160.digest, testFileRIPEMD160, 20) == 0 && + memcmp(RIPEMD160Copy.digest, testFileRIPEMD160, 20) == 0) EXPECT_EXCEPTION(@"Detect invalid call of " @"-[updateWithBuffer:length]", OFHashAlreadyCalculatedException, - [rmd160 updateWithBuffer: "" length: 1]) + [RIPEMD160 updateWithBuffer: "" length: 1]) objc_autoreleasePoolPop(pool); } @end Index: tests/OFSHA1HashTests.m ================================================================== --- tests/OFSHA1HashTests.m +++ tests/OFSHA1HashTests.m @@ -17,41 +17,41 @@ #include #import "TestsAppDelegate.h" -static OFString *module = @"OFSHA1Hash"; +static OFString *const module = @"OFSHA1Hash"; -const uint8_t testfile_sha1[20] = +const uint8_t testFileSHA1[20] = "\xC9\x9A\xB8\x7E\x1E\xC8\xEC\x65\xD5\xEB\xE4\x2E\x0D\xA6\x80\x96\xF5" "\x94\xE7\x17"; @implementation TestsAppDelegate (SHA1HashTests) - (void)SHA1HashTests { void *pool = objc_autoreleasePoolPush(); - OFSHA1Hash *sha1, *copy; - OFFile *f = [OFFile fileWithPath: @"testfile.bin" mode: @"r"]; + OFSHA1Hash *SHA1, *SHA1Copy; + OFFile *file = [OFFile fileWithPath: @"testfile.bin" mode: @"r"]; TEST(@"+[hashWithAllowsSwappableMemory:]", - (sha1 = [OFSHA1Hash hashWithAllowsSwappableMemory: true])) - - while (!f.atEndOfStream) { - char buf[64]; - size_t len = [f readIntoBuffer: buf length: 64]; - [sha1 updateWithBuffer: buf length: len]; - } - [f close]; - - TEST(@"-[copy]", (copy = [[sha1 copy] autorelease])) + (SHA1 = [OFSHA1Hash hashWithAllowsSwappableMemory: true])) + + while (!file.atEndOfStream) { + char buffer[64]; + size_t length = [file readIntoBuffer: buffer length: 64]; + [SHA1 updateWithBuffer: buffer length: length]; + } + [file close]; + + TEST(@"-[copy]", (SHA1Copy = [[SHA1 copy] autorelease])) TEST(@"-[digest]", - memcmp(sha1.digest, testfile_sha1, 20) == 0 && - memcmp(copy.digest, testfile_sha1, 20) == 0) + memcmp(SHA1.digest, testFileSHA1, 20) == 0 && + memcmp(SHA1Copy.digest, testFileSHA1, 20) == 0) EXPECT_EXCEPTION(@"Detect invalid call of " @"-[updateWithBuffer:length:]", OFHashAlreadyCalculatedException, - [sha1 updateWithBuffer: "" length: 1]) + [SHA1 updateWithBuffer: "" length: 1]) objc_autoreleasePoolPop(pool); } @end Index: tests/OFSHA224HashTests.m ================================================================== --- tests/OFSHA224HashTests.m +++ tests/OFSHA224HashTests.m @@ -17,41 +17,41 @@ #include #import "TestsAppDelegate.h" -static OFString *module = @"OFSHA224Hash"; +static OFString *const module = @"OFSHA224Hash"; -const uint8_t testfile_sha224[28] = +const uint8_t testFileSHA224[28] = "\x27\x69\xD8\x04\x2D\x0F\xCA\x84\x6C\xF1\x62\x44\xBA\x0C\xBD\x46\x64" "\x5F\x4F\x20\x02\x4D\x15\xED\x1C\x61\x1F\xF7"; @implementation TestsAppDelegate (SHA224HashTests) - (void)SHA224HashTests { void *pool = objc_autoreleasePoolPush(); - OFSHA224Hash *sha224, *copy; - OFFile *f = [OFFile fileWithPath: @"testfile.bin" mode: @"r"]; + OFSHA224Hash *SHA224, *SHA224Copy; + OFFile *file = [OFFile fileWithPath: @"testfile.bin" mode: @"r"]; TEST(@"+[hashWithAllowsSwappableMemory:]", - (sha224 = [OFSHA224Hash hashWithAllowsSwappableMemory: true])) - - while (!f.atEndOfStream) { - char buf[64]; - size_t len = [f readIntoBuffer: buf length: 64]; - [sha224 updateWithBuffer: buf length: len]; - } - [f close]; - - TEST(@"-[copy]", (copy = [[sha224 copy] autorelease])) + (SHA224 = [OFSHA224Hash hashWithAllowsSwappableMemory: true])) + + while (!file.atEndOfStream) { + char buffer[64]; + size_t length = [file readIntoBuffer: buffer length: 64]; + [SHA224 updateWithBuffer: buffer length: length]; + } + [file close]; + + TEST(@"-[copy]", (SHA224Copy = [[SHA224 copy] autorelease])) TEST(@"-[digest]", - memcmp(sha224.digest, testfile_sha224, 28) == 0 && - memcmp(copy.digest, testfile_sha224, 28) == 0) + memcmp(SHA224.digest, testFileSHA224, 28) == 0 && + memcmp(SHA224Copy.digest, testFileSHA224, 28) == 0) EXPECT_EXCEPTION(@"Detect invalid call of " @"-[updateWithBuffer:length:]", OFHashAlreadyCalculatedException, - [sha224 updateWithBuffer: "" length: 1]) + [SHA224 updateWithBuffer: "" length: 1]) objc_autoreleasePoolPop(pool); } @end Index: tests/OFSHA256HashTests.m ================================================================== --- tests/OFSHA256HashTests.m +++ tests/OFSHA256HashTests.m @@ -17,41 +17,41 @@ #include #import "TestsAppDelegate.h" -static OFString *module = @"OFSHA256Hash"; +static OFString *const module = @"OFSHA256Hash"; -const uint8_t testfile_sha256[32] = +const uint8_t testFileSHA256[32] = "\x1A\x02\xD6\x46\xF5\xA6\xBA\xAA\xFF\x7F\xD5\x87\xBA\xC3\xF6\xC6\xB5" "\x67\x93\x8F\x0F\x44\x90\xB8\xF5\x35\x89\xF0\x5A\x23\x7F\x69"; @implementation TestsAppDelegate (SHA256HashTests) - (void)SHA256HashTests { void *pool = objc_autoreleasePoolPush(); - OFSHA256Hash *sha256, *copy; - OFFile *f = [OFFile fileWithPath: @"testfile.bin" mode: @"r"]; + OFSHA256Hash *SHA256, *SHA256Copy; + OFFile *file = [OFFile fileWithPath: @"testfile.bin" mode: @"r"]; TEST(@"+[hashWithAllowsSwappableMemory:]", - (sha256 = [OFSHA256Hash hashWithAllowsSwappableMemory: true])) - - while (!f.atEndOfStream) { - char buf[64]; - size_t len = [f readIntoBuffer: buf length: 64]; - [sha256 updateWithBuffer: buf length: len]; - } - [f close]; - - TEST(@"-[copy]", (copy = [[sha256 copy] autorelease])) + (SHA256 = [OFSHA256Hash hashWithAllowsSwappableMemory: true])) + + while (!file.atEndOfStream) { + char buffer[64]; + size_t length = [file readIntoBuffer: buffer length: 64]; + [SHA256 updateWithBuffer: buffer length: length]; + } + [file close]; + + TEST(@"-[copy]", (SHA256Copy = [[SHA256 copy] autorelease])) TEST(@"-[digest]", - memcmp(sha256.digest, testfile_sha256, 32) == 0 && - memcmp(copy.digest, testfile_sha256, 32) == 0) + memcmp(SHA256.digest, testFileSHA256, 32) == 0 && + memcmp(SHA256Copy.digest, testFileSHA256, 32) == 0) EXPECT_EXCEPTION(@"Detect invalid call of " @"-[updateWithBuffer:length:]", OFHashAlreadyCalculatedException, - [sha256 updateWithBuffer: "" length: 1]) + [SHA256 updateWithBuffer: "" length: 1]) objc_autoreleasePoolPop(pool); } @end Index: tests/OFSHA384HashTests.m ================================================================== --- tests/OFSHA384HashTests.m +++ tests/OFSHA384HashTests.m @@ -17,42 +17,42 @@ #include #import "TestsAppDelegate.h" -static OFString *module = @"OFSHA384Hash"; +static OFString *const module = @"OFSHA384Hash"; -const uint8_t testfile_sha384[48] = +const uint8_t testFileSHA384[48] = "\x7E\xDE\x62\xE2\x10\xA5\x1E\x18\x8A\x11\x7F\x78\xD7\xC7\x55\xB6\x43" "\x94\x1B\xD2\x78\x5C\xCF\xF3\x8A\xB8\x98\x22\xC7\x0E\xFE\xF1\xEC\x53" "\xE9\x1A\xB3\x51\x70\x8C\x1F\x3F\x56\x12\x44\x01\x91\x54"; @implementation TestsAppDelegate (SHA384HashTests) - (void)SHA384HashTests { void *pool = objc_autoreleasePoolPush(); - OFSHA384Hash *sha384, *copy; - OFFile *f = [OFFile fileWithPath: @"testfile.bin" mode: @"r"]; + OFSHA384Hash *SHA384, *SHA384Copy; + OFFile *file = [OFFile fileWithPath: @"testfile.bin" mode: @"r"]; TEST(@"+[hashWithAllowsSwappableMemory:]", - (sha384 = [OFSHA384Hash hashWithAllowsSwappableMemory: true])) - - while (!f.atEndOfStream) { - char buf[128]; - size_t len = [f readIntoBuffer: buf length: 128]; - [sha384 updateWithBuffer: buf length: len]; - } - [f close]; - - TEST(@"-[copy]", (copy = [[sha384 copy] autorelease])) + (SHA384 = [OFSHA384Hash hashWithAllowsSwappableMemory: true])) + + while (!file.atEndOfStream) { + char buffer[128]; + size_t length = [file readIntoBuffer: buffer length: 128]; + [SHA384 updateWithBuffer: buffer length: length]; + } + [file close]; + + TEST(@"-[copy]", (SHA384Copy = [[SHA384 copy] autorelease])) TEST(@"-[digest]", - memcmp(sha384.digest, testfile_sha384, 48) == 0 && - memcmp(copy.digest, testfile_sha384, 48) == 0) + memcmp(SHA384.digest, testFileSHA384, 48) == 0 && + memcmp(SHA384Copy.digest, testFileSHA384, 48) == 0) EXPECT_EXCEPTION(@"Detect invalid call of " @"-[updateWithBuffer:length:]", OFHashAlreadyCalculatedException, - [sha384 updateWithBuffer: "" length: 1]) + [SHA384 updateWithBuffer: "" length: 1]) objc_autoreleasePoolPop(pool); } @end Index: tests/OFSHA512HashTests.m ================================================================== --- tests/OFSHA512HashTests.m +++ tests/OFSHA512HashTests.m @@ -17,43 +17,43 @@ #include #import "TestsAppDelegate.h" -static OFString *module = @"OFSHA512Hash"; +static OFString *const module = @"OFSHA512Hash"; -const uint8_t testfile_sha512[64] = +const uint8_t testFileSHA512[64] = "\x8F\x36\x6E\x3C\x19\x4B\xBB\xC7\x82\xAA\xCD\x7D\x55\xA2\xD3\x29\x29" "\x97\x6A\x3F\xEB\x9B\xB2\xCB\x75\xC9\xEC\xC8\x10\x07\xD6\x07\x31\x4A" "\xB1\x30\x97\x82\x58\xA5\x1F\x71\x42\xE6\x56\x07\x99\x57\xB2\xB8\x3B" "\xA1\x8A\x41\x64\x33\x69\x21\x8C\x2A\x44\x6D\xF2\xA0"; @implementation TestsAppDelegate (SHA512HashTests) - (void)SHA512HashTests { void *pool = objc_autoreleasePoolPush(); - OFSHA512Hash *sha512, *copy; - OFFile *f = [OFFile fileWithPath: @"testfile.bin" mode: @"r"]; + OFSHA512Hash *SHA512, *SHA512Copy; + OFFile *file = [OFFile fileWithPath: @"testfile.bin" mode: @"r"]; TEST(@"+[hashWithAllowsSwappableMemory:]", - (sha512 = [OFSHA512Hash hashWithAllowsSwappableMemory: true])) - - while (!f.atEndOfStream) { - char buf[128]; - size_t len = [f readIntoBuffer: buf length: 128]; - [sha512 updateWithBuffer: buf length: len]; - } - [f close]; - - TEST(@"-[copy]", (copy = [[sha512 copy] autorelease])) + (SHA512 = [OFSHA512Hash hashWithAllowsSwappableMemory: true])) + + while (!file.atEndOfStream) { + char buffer[128]; + size_t length = [file readIntoBuffer: buffer length: 128]; + [SHA512 updateWithBuffer: buffer length: length]; + } + [file close]; + + TEST(@"-[copy]", (SHA512Copy = [[SHA512 copy] autorelease])) TEST(@"-[digest]", - memcmp(sha512.digest, testfile_sha512, 64) == 0 && - memcmp(copy.digest, testfile_sha512, 64) == 0) + memcmp(SHA512.digest, testFileSHA512, 64) == 0 && + memcmp(SHA512Copy.digest, testFileSHA512, 64) == 0) EXPECT_EXCEPTION(@"Detect invalid call of " @"-[updateWithBuffer:length:]", OFHashAlreadyCalculatedException, - [sha512 updateWithBuffer: "" length: 1]) + [SHA512 updateWithBuffer: "" length: 1]) objc_autoreleasePoolPop(pool); } @end Index: tests/OFSPXSocketTests.m ================================================================== --- tests/OFSPXSocketTests.m +++ tests/OFSPXSocketTests.m @@ -17,11 +17,11 @@ #include #import "TestsAppDelegate.h" -static OFString *module = @"OFSPXSocket"; +static OFString *const module = @"OFSPXSocket"; @interface SPXSocketDelegate: OFObject { @public OFSequencedPacketSocket *_expectedServerSocket; Index: tests/OFSPXStreamSocketTests.m ================================================================== --- tests/OFSPXStreamSocketTests.m +++ tests/OFSPXStreamSocketTests.m @@ -17,11 +17,11 @@ #include #import "TestsAppDelegate.h" -static OFString *module = @"OFSPXStreamSocket"; +static OFString *const module = @"OFSPXStreamSocket"; @interface SPXStreamSocketDelegate: OFObject { @public OFStreamSocket *_expectedServerSocket; ADDED tests/OFScryptTests.m Index: tests/OFScryptTests.m ================================================================== --- tests/OFScryptTests.m +++ tests/OFScryptTests.m @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2008-2021 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#include + +#import "TestsAppDelegate.h" + +static OFString *const module = @"OFScrypt"; +/* Test vectors form RFC 7914 */ +static const unsigned char salsa20Input[64] = { + 0x7E, 0x87, 0x9A, 0x21, 0x4F, 0x3E, 0xC9, 0x86, 0x7C, 0xA9, 0x40, 0xE6, + 0x41, 0x71, 0x8F, 0x26, 0xBA, 0xEE, 0x55, 0x5B, 0x8C, 0x61, 0xC1, 0xB5, + 0x0D, 0xF8, 0x46, 0x11, 0x6D, 0xCD, 0x3B, 0x1D, 0xEE, 0x24, 0xF3, 0x19, + 0xDF, 0x9B, 0x3D, 0x85, 0x14, 0x12, 0x1E, 0x4B, 0x5A, 0xC5, 0xAA, 0x32, + 0x76, 0x02, 0x1D, 0x29, 0x09, 0xC7, 0x48, 0x29, 0xED, 0xEB, 0xC6, 0x8D, + 0xB8, 0xB8, 0xC2, 0x5E +}; +static const unsigned char salsa20Output[64] = { + 0xA4, 0x1F, 0x85, 0x9C, 0x66, 0x08, 0xCC, 0x99, 0x3B, 0x81, 0xCA, 0xCB, + 0x02, 0x0C, 0xEF, 0x05, 0x04, 0x4B, 0x21, 0x81, 0xA2, 0xFD, 0x33, 0x7D, + 0xFD, 0x7B, 0x1C, 0x63, 0x96, 0x68, 0x2F, 0x29, 0xB4, 0x39, 0x31, 0x68, + 0xE3, 0xC9, 0xE6, 0xBC, 0xFE, 0x6B, 0xC5, 0xB7, 0xA0, 0x6D, 0x96, 0xBA, + 0xE4, 0x24, 0xCC, 0x10, 0x2C, 0x91, 0x74, 0x5C, 0x24, 0xAD, 0x67, 0x3D, + 0xC7, 0x61, 0x8F, 0x81 +}; +static const union { + unsigned char uc[128]; + uint32_t u32[32]; +} blockMixInput = { .uc = { + 0xF7, 0xCE, 0x0B, 0x65, 0x3D, 0x2D, 0x72, 0xA4, 0x10, 0x8C, 0xF5, 0xAB, + 0xE9, 0x12, 0xFF, 0xDD, 0x77, 0x76, 0x16, 0xDB, 0xBB, 0x27, 0xA7, 0x0E, + 0x82, 0x04, 0xF3, 0xAE, 0x2D, 0x0F, 0x6F, 0xAD, 0x89, 0xF6, 0x8F, 0x48, + 0x11, 0xD1, 0xE8, 0x7B, 0xCC, 0x3B, 0xD7, 0x40, 0x0A, 0x9F, 0xFD, 0x29, + 0x09, 0x4F, 0x01, 0x84, 0x63, 0x95, 0x74, 0xF3, 0x9A, 0xE5, 0xA1, 0x31, + 0x52, 0x17, 0xBC, 0xD7, + 0x89, 0x49, 0x91, 0x44, 0x72, 0x13, 0xBB, 0x22, 0x6C, 0x25, 0xB5, 0x4D, + 0xA8, 0x63, 0x70, 0xFB, 0xCD, 0x98, 0x43, 0x80, 0x37, 0x46, 0x66, 0xBB, + 0x8F, 0xFC, 0xB5, 0xBF, 0x40, 0xC2, 0x54, 0xB0, 0x67, 0xD2, 0x7C, 0x51, + 0xCE, 0x4A, 0xD5, 0xFE, 0xD8, 0x29, 0xC9, 0x0B, 0x50, 0x5A, 0x57, 0x1B, + 0x7F, 0x4D, 0x1C, 0xAD, 0x6A, 0x52, 0x3C, 0xDA, 0x77, 0x0E, 0x67, 0xBC, + 0xEA, 0xAF, 0x7E, 0x89 +}}; +static const unsigned char blockMixOutput[128] = { + 0xA4, 0x1F, 0x85, 0x9C, 0x66, 0x08, 0xCC, 0x99, 0x3B, 0x81, 0xCA, 0xCB, + 0x02, 0x0C, 0xEF, 0x05, 0x04, 0x4B, 0x21, 0x81, 0xA2, 0xFD, 0x33, 0x7D, + 0xFD, 0x7B, 0x1C, 0x63, 0x96, 0x68, 0x2F, 0x29, 0xB4, 0x39, 0x31, 0x68, + 0xE3, 0xC9, 0xE6, 0xBC, 0xFE, 0x6B, 0xC5, 0xB7, 0xA0, 0x6D, 0x96, 0xBA, + 0xE4, 0x24, 0xCC, 0x10, 0x2C, 0x91, 0x74, 0x5C, 0x24, 0xAD, 0x67, 0x3D, + 0xC7, 0x61, 0x8F, 0x81, + 0x20, 0xED, 0xC9, 0x75, 0x32, 0x38, 0x81, 0xA8, 0x05, 0x40, 0xF6, 0x4C, + 0x16, 0x2D, 0xCD, 0x3C, 0x21, 0x07, 0x7C, 0xFE, 0x5F, 0x8D, 0x5F, 0xE2, + 0xB1, 0xA4, 0x16, 0x8F, 0x95, 0x36, 0x78, 0xB7, 0x7D, 0x3B, 0x3D, 0x80, + 0x3B, 0x60, 0xE4, 0xAB, 0x92, 0x09, 0x96, 0xE5, 0x9B, 0x4D, 0x53, 0xB6, + 0x5D, 0x2A, 0x22, 0x58, 0x77, 0xD5, 0xED, 0xF5, 0x84, 0x2C, 0xB9, 0xF1, + 0x4E, 0xEF, 0xE4, 0x25 +}; +static const unsigned char ROMixInput[128] = { + 0xF7, 0xCE, 0x0B, 0x65, 0x3D, 0x2D, 0x72, 0xA4, 0x10, 0x8C, 0xF5, 0xAB, + 0xE9, 0x12, 0xFF, 0xDD, 0x77, 0x76, 0x16, 0xDB, 0xBB, 0x27, 0xA7, 0x0E, + 0x82, 0x04, 0xF3, 0xAE, 0x2D, 0x0F, 0x6F, 0xAD, 0x89, 0xF6, 0x8F, 0x48, + 0x11, 0xD1, 0xE8, 0x7B, 0xCC, 0x3B, 0xD7, 0x40, 0x0A, 0x9F, 0xFD, 0x29, + 0x09, 0x4F, 0x01, 0x84, 0x63, 0x95, 0x74, 0xF3, 0x9A, 0xE5, 0xA1, 0x31, + 0x52, 0x17, 0xBC, 0xD7, 0x89, 0x49, 0x91, 0x44, 0x72, 0x13, 0xBB, 0x22, + 0x6C, 0x25, 0xB5, 0x4D, 0xA8, 0x63, 0x70, 0xFB, 0xCD, 0x98, 0x43, 0x80, + 0x37, 0x46, 0x66, 0xBB, 0x8F, 0xFC, 0xB5, 0xBF, 0x40, 0xC2, 0x54, 0xB0, + 0x67, 0xD2, 0x7C, 0x51, 0xCE, 0x4A, 0xD5, 0xFE, 0xD8, 0x29, 0xC9, 0x0B, + 0x50, 0x5A, 0x57, 0x1B, 0x7F, 0x4D, 0x1C, 0xAD, 0x6A, 0x52, 0x3C, 0xDA, + 0x77, 0x0E, 0x67, 0xBC, 0xEA, 0xAF, 0x7E, 0x89 +}; +static const unsigned char ROMixOutput[128] = { + 0x79, 0xCC, 0xC1, 0x93, 0x62, 0x9D, 0xEB, 0xCA, 0x04, 0x7F, 0x0B, 0x70, + 0x60, 0x4B, 0xF6, 0xB6, 0x2C, 0xE3, 0xDD, 0x4A, 0x96, 0x26, 0xE3, 0x55, + 0xFA, 0xFC, 0x61, 0x98, 0xE6, 0xEA, 0x2B, 0x46, 0xD5, 0x84, 0x13, 0x67, + 0x3B, 0x99, 0xB0, 0x29, 0xD6, 0x65, 0xC3, 0x57, 0x60, 0x1F, 0xB4, 0x26, + 0xA0, 0xB2, 0xF4, 0xBB, 0xA2, 0x00, 0xEE, 0x9F, 0x0A, 0x43, 0xD1, 0x9B, + 0x57, 0x1A, 0x9C, 0x71, 0xEF, 0x11, 0x42, 0xE6, 0x5D, 0x5A, 0x26, 0x6F, + 0xDD, 0xCA, 0x83, 0x2C, 0xE5, 0x9F, 0xAA, 0x7C, 0xAC, 0x0B, 0x9C, 0xF1, + 0xBE, 0x2B, 0xFF, 0xCA, 0x30, 0x0D, 0x01, 0xEE, 0x38, 0x76, 0x19, 0xC4, + 0xAE, 0x12, 0xFD, 0x44, 0x38, 0xF2, 0x03, 0xA0, 0xE4, 0xE1, 0xC4, 0x7E, + 0xC3, 0x14, 0x86, 0x1F, 0x4E, 0x90, 0x87, 0xCB, 0x33, 0x39, 0x6A, 0x68, + 0x73, 0xE8, 0xF9, 0xD2, 0x53, 0x9A, 0x4B, 0x8E +}; +static const unsigned char testVector1[64] = { + 0x77, 0xD6, 0x57, 0x62, 0x38, 0x65, 0x7B, 0x20, 0x3B, 0x19, 0xCA, 0x42, + 0xC1, 0x8A, 0x04, 0x97, 0xF1, 0x6B, 0x48, 0x44, 0xE3, 0x07, 0x4A, 0xE8, + 0xDF, 0xDF, 0xFA, 0x3F, 0xED, 0xE2, 0x14, 0x42, 0xFC, 0xD0, 0x06, 0x9D, + 0xED, 0x09, 0x48, 0xF8, 0x32, 0x6A, 0x75, 0x3A, 0x0F, 0xC8, 0x1F, 0x17, + 0xE8, 0xD3, 0xE0, 0xFB, 0x2E, 0x0D, 0x36, 0x28, 0xCF, 0x35, 0xE2, 0x0C, + 0x38, 0xD1, 0x89, 0x06 +}; +static const unsigned char testVector2[64] = { + 0xFD, 0xBA, 0xBE, 0x1C, 0x9D, 0x34, 0x72, 0x00, 0x78, 0x56, 0xE7, 0x19, + 0x0D, 0x01, 0xE9, 0xFE, 0x7C, 0x6A, 0xD7, 0xCB, 0xC8, 0x23, 0x78, 0x30, + 0xE7, 0x73, 0x76, 0x63, 0x4B, 0x37, 0x31, 0x62, 0x2E, 0xAF, 0x30, 0xD9, + 0x2E, 0x22, 0xA3, 0x88, 0x6F, 0xF1, 0x09, 0x27, 0x9D, 0x98, 0x30, 0xDA, + 0xC7, 0x27, 0xAF, 0xB9, 0x4A, 0x83, 0xEE, 0x6D, 0x83, 0x60, 0xCB, 0xDF, + 0xA2, 0xCC, 0x06, 0x40 +}; +static const unsigned char testVector3[64] = { + 0x70, 0x23, 0xBD, 0xCB, 0x3A, 0xFD, 0x73, 0x48, 0x46, 0x1C, 0x06, 0xCD, + 0x81, 0xFD, 0x38, 0xEB, 0xFD, 0xA8, 0xFB, 0xBA, 0x90, 0x4F, 0x8E, 0x3E, + 0xA9, 0xB5, 0x43, 0xF6, 0x54, 0x5D, 0xA1, 0xF2, 0xD5, 0x43, 0x29, 0x55, + 0x61, 0x3F, 0x0F, 0xCF, 0x62, 0xD4, 0x97, 0x05, 0x24, 0x2A, 0x9A, 0xF9, + 0xE6, 0x1E, 0x85, 0xDC, 0x0D, 0x65, 0x1E, 0x40, 0xDF, 0xCF, 0x01, 0x7B, + 0x45, 0x57, 0x58, 0x87 +}; +/* The forth test vector is too expensive to include it in the tests. */ +#if 0 +static const unsigned char testVector4[64] = { + 0x21, 0x01, 0xCB, 0x9B, 0x6A, 0x51, 0x1A, 0xAE, 0xAD, 0xDB, 0xBE, 0x09, + 0xCF, 0x70, 0xF8, 0x81, 0xEC, 0x56, 0x8D, 0x57, 0x4A, 0x2F, 0xFD, 0x4D, + 0xAB, 0xE5, 0xEE, 0x98, 0x20, 0xAD, 0xAA, 0x47, 0x8E, 0x56, 0xFD, 0x8F, + 0x4B, 0xA5, 0xD0, 0x9F, 0xFA, 0x1C, 0x6D, 0x92, 0x7C, 0x40, 0xF4, 0xC3, + 0x37, 0x30, 0x40, 0x49, 0xE8, 0xA9, 0x52, 0xFB, 0xCB, 0xF4, 0x5C, 0x6F, + 0xA7, 0x7A, 0x41, 0xA4 +}; +#endif + +@implementation TestsAppDelegate (OFScryptTests) +- (void)scryptTests +{ + void *pool = objc_autoreleasePoolPush(); + uint32_t salsa20Buffer[16]; + uint32_t blockMixBuffer[32]; + uint32_t ROMixBuffer[32], ROMixTmp[17 * 32]; + unsigned char output[64]; + + TEST(@"Salsa20/8 Core", + R(memcpy(salsa20Buffer, salsa20Input, 64)) && + R(OFSalsa20_8Core(salsa20Buffer)) && + memcmp(salsa20Buffer, salsa20Output, 64) == 0) + + TEST(@"Block mix", + R(OFScryptBlockMix(blockMixBuffer, blockMixInput.u32, 1)) && + memcmp(blockMixBuffer, blockMixOutput, 128) == 0) + + TEST(@"ROMix", + R(memcpy(ROMixBuffer, ROMixInput, 128)) && + R(OFScryptROMix(ROMixBuffer, 1, 16, ROMixTmp)) && + memcmp(ROMixBuffer, ROMixOutput, 128) == 0) + + TEST(@"scrypt test vector #1", + R(OFScrypt((OFScryptParameters){ + .blockSize = 1, + .costFactor = 16, + .parallelization = 1, + .salt = (unsigned char *)"", + .saltLength = 0, + .password = "", + .passwordLength = 0, + .key = output, + .keyLength = 64, + .allowsSwappableMemory = true + })) && memcmp(output, testVector1, 64) == 0) + + TEST(@"scrypt test vector #2", + R(OFScrypt((OFScryptParameters){ + .blockSize = 8, + .costFactor = 1024, + .parallelization = 16, + .salt = (unsigned char *)"NaCl", + .saltLength = 4, + .password = "password", + .passwordLength = 8, + .key = output, + .keyLength = 64, + .allowsSwappableMemory = true + })) && memcmp(output, testVector2, 64) == 0) + + TEST(@"scrypt test vector #3", + R(OFScrypt((OFScryptParameters){ + .blockSize = 8, + .costFactor = 16384, + .parallelization = 1, + .salt = (unsigned char *)"SodiumChloride", + .saltLength = 14, + .password = "pleaseletmein", + .passwordLength = 13, + .key = output, + .keyLength = 64, + .allowsSwappableMemory = true + })) && memcmp(output, testVector3, 64) == 0) + + /* The forth test vector is too expensive to include it in the tests. */ +#if 0 + TEST(@"scrypt test vector #4", + R(OFScrypt((OFScryptParameters){ + .blockSize = 8, + .costFactor = 1048576, + .parallelization = 1, + .salt = (unsigned char *)"SodiumChloride", + .saltLength = 14, + .password = "pleaseletmein", + .passwordLength = 13, + .key = output, + .keyLength = 64, + .allowsSwappableMemory = true + })) && memcmp(output, testVector4, 64) == 0) +#endif + + objc_autoreleasePoolPop(pool); +} +@end Index: tests/OFSerializationTests.m ================================================================== --- tests/OFSerializationTests.m +++ tests/OFSerializationTests.m @@ -15,50 +15,52 @@ #include "config.h" #import "TestsAppDelegate.h" -static OFString *module = @"OFSerialization"; +static OFString *const module = @"OFSerialization"; @implementation TestsAppDelegate (OFSerializationTests) - (void)serializationTests { void *pool = objc_autoreleasePoolPush(); - OFMutableDictionary *d = [OFMutableDictionary dictionary]; - OFMutableArray *a = [OFMutableArray array]; - OFList *l = [OFList list]; - OFData *data; - OFString *s; - - [a addObject: @"Qu\"xbar\ntest"]; - [a addObject: [OFNumber numberWithInt: 1234]]; - [a addObject: [OFNumber numberWithDouble: 1234.5678]]; - [a addObject: [OFMutableString stringWithString: @"asd"]]; - [a addObject: [OFDate dateWithTimeIntervalSince1970: 1234.5678]]; - - [d setObject: @"Hello" forKey: a]; - [d setObject: @"B\"la" forKey: @"Blub"]; - - [l appendObject: @"Hello"]; - [l appendObject: @"Wo\rld!\nHow are you?"]; - [l appendObject: [OFURL URLWithString: @"https://objfw.nil.im/"]]; - [l appendObject: - [OFXMLElement elementWithXMLString: @""]]; - [l appendObject: [OFSet setWithObjects: @"foo", @"foo", @"bar", nil]]; - [l appendObject: + OFMutableDictionary *dict = [OFMutableDictionary dictionary]; + OFMutableArray *array = [OFMutableArray array]; + OFList *list = [OFList list]; + OFData *data; + OFString *string; + + [array addObject: @"Qu\"xbar\ntest"]; + [array addObject: [OFNumber numberWithInt: 1234]]; + [array addObject: [OFNumber numberWithDouble: 1234.5678]]; + [array addObject: [OFMutableString stringWithString: @"asd"]]; + [array addObject: [OFDate dateWithTimeIntervalSince1970: 1234.5678]]; + + [dict setObject: @"Hello" forKey: array]; + [dict setObject: @"B\"la" forKey: @"Blub"]; + + [list appendObject: @"Hello"]; + [list appendObject: @"Wo\rld!\nHow are you?"]; + [list appendObject: [OFURL URLWithString: @"https://objfw.nil.im/"]]; + [list appendObject: + [OFXMLElement elementWithXMLString: @""]]; + [list appendObject: + [OFSet setWithObjects: @"foo", @"foo", @"bar", nil]]; + [list appendObject: [OFCountedSet setWithObjects: @"foo", @"foo", @"bar", nil]]; - [d setObject: @"list" forKey: l]; + [dict setObject: @"list" forKey: list]; data = [OFData dataWithItems: "0123456789:; + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "TestsAppDelegate.h" + +#define COMPARE_V6(a, a0, a1, a2, a3, a4, a5, a6, a7) \ + (a.sockaddr.in6.sin6_addr.s6_addr[0] == (a0 >> 8) && \ + a.sockaddr.in6.sin6_addr.s6_addr[1] == (a0 & 0xFF) && \ + a.sockaddr.in6.sin6_addr.s6_addr[2] == (a1 >> 8) && \ + a.sockaddr.in6.sin6_addr.s6_addr[3] == (a1 & 0xFF) && \ + a.sockaddr.in6.sin6_addr.s6_addr[4] == (a2 >> 8) && \ + a.sockaddr.in6.sin6_addr.s6_addr[5] == (a2 & 0xFF) && \ + a.sockaddr.in6.sin6_addr.s6_addr[6] == (a3 >> 8) && \ + a.sockaddr.in6.sin6_addr.s6_addr[7] == (a3 & 0xFF) && \ + a.sockaddr.in6.sin6_addr.s6_addr[8] == (a4 >> 8) && \ + a.sockaddr.in6.sin6_addr.s6_addr[9] == (a4 & 0xFF) && \ + a.sockaddr.in6.sin6_addr.s6_addr[10] == (a5 >> 8) && \ + a.sockaddr.in6.sin6_addr.s6_addr[11] == (a5 & 0xFF) && \ + a.sockaddr.in6.sin6_addr.s6_addr[12] == (a6 >> 8) && \ + a.sockaddr.in6.sin6_addr.s6_addr[13] == (a6 & 0xFF) && \ + a.sockaddr.in6.sin6_addr.s6_addr[14] == (a7 >> 8) && \ + a.sockaddr.in6.sin6_addr.s6_addr[15] == (a7 & 0xFF)) +#define SET_V6(a, a0, a1, a2, a3, a4, a5, a6, a7) \ + a.sockaddr.in6.sin6_addr.s6_addr[0] = a0 >> 8; \ + a.sockaddr.in6.sin6_addr.s6_addr[1] = a0 & 0xFF; \ + a.sockaddr.in6.sin6_addr.s6_addr[2] = a1 >> 8; \ + a.sockaddr.in6.sin6_addr.s6_addr[3] = a1 & 0xFF; \ + a.sockaddr.in6.sin6_addr.s6_addr[4] = a2 >> 8; \ + a.sockaddr.in6.sin6_addr.s6_addr[5] = a2 & 0xFF; \ + a.sockaddr.in6.sin6_addr.s6_addr[6] = a3 >> 8; \ + a.sockaddr.in6.sin6_addr.s6_addr[7] = a3 & 0xFF; \ + a.sockaddr.in6.sin6_addr.s6_addr[8] = a4 >> 8; \ + a.sockaddr.in6.sin6_addr.s6_addr[9] = a4 & 0xFF; \ + a.sockaddr.in6.sin6_addr.s6_addr[10] = a5 >> 8; \ + a.sockaddr.in6.sin6_addr.s6_addr[11] = a5 & 0xFF; \ + a.sockaddr.in6.sin6_addr.s6_addr[12] = a6 >> 8; \ + a.sockaddr.in6.sin6_addr.s6_addr[13] = a6 & 0xFF; \ + a.sockaddr.in6.sin6_addr.s6_addr[14] = a7 >> 8; \ + a.sockaddr.in6.sin6_addr.s6_addr[15] = a7 & 0xFF; + +static OFString *const module = @"OFSocket"; + +@implementation TestsAppDelegate (OFSocketTests) +- (void)socketTests +{ + void *pool = objc_autoreleasePoolPush(); + OFSocketAddress addr; + + TEST(@"Parsing an IPv4", + R(addr = OFSocketAddressParseIP(@"127.0.0.1", 1234)) && + OFFromBigEndian32(addr.sockaddr.in.sin_addr.s_addr) == 0x7F000001 && + OFFromBigEndian16(addr.sockaddr.in.sin_port) == 1234) + + EXPECT_EXCEPTION(@"Refusing invalid IPv4 #1", OFInvalidFormatException, + OFSocketAddressParseIP(@"127.0.0.0.1", 1234)) + + EXPECT_EXCEPTION(@"Refusing invalid IPv4 #2", OFInvalidFormatException, + OFSocketAddressParseIP(@"127.0.0.256", 1234)) + + EXPECT_EXCEPTION(@"Refusing invalid IPv4 #3", OFInvalidFormatException, + OFSocketAddressParseIP(@"127.0.0. 1", 1234)) + + EXPECT_EXCEPTION(@"Refusing invalid IPv4 #4", OFInvalidFormatException, + OFSocketAddressParseIP(@" 127.0.0.1", 1234)) + + EXPECT_EXCEPTION(@"Refusing invalid IPv4 #5", OFInvalidFormatException, + OFSocketAddressParseIP(@"127.0.a.1", 1234)) + + EXPECT_EXCEPTION(@"Refusing invalid IPv4 #6", OFInvalidFormatException, + OFSocketAddressParseIP(@"127.0..1", 1234)) + + TEST(@"Port of an IPv4 address", OFSocketAddressPort(&addr) == 1234) + + TEST(@"Converting an IPv4 to a string", + [OFSocketAddressString(&addr) isEqual: @"127.0.0.1"]) + + TEST(@"Parsing an IPv6 #1", + R(addr = OFSocketAddressParseIP( + @"1122:3344:5566:7788:99aa:bbCc:ddee:ff00", 1234)) && + COMPARE_V6(addr, + 0x1122, 0x3344, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0xDDEE, 0xFF00) && + OFFromBigEndian16(addr.sockaddr.in6.sin6_port) == 1234) + + TEST(@"Parsing an IPv6 #2", + R(addr = OFSocketAddressParseIP(@"::", 1234)) && + COMPARE_V6(addr, 0, 0, 0, 0, 0, 0, 0, 0) && + OFFromBigEndian16(addr.sockaddr.in6.sin6_port) == 1234) + + TEST(@"Parsing an IPv6 #3", + R(addr = OFSocketAddressParseIP(@"aaAa::bBbb", 1234)) && + COMPARE_V6(addr, 0xAAAA, 0, 0, 0, 0, 0, 0, 0xBBBB) && + OFFromBigEndian16(addr.sockaddr.in6.sin6_port) == 1234) + + TEST(@"Parsing an IPv6 #4", + R(addr = OFSocketAddressParseIP(@"aaAa::", 1234)) && + COMPARE_V6(addr, 0xAAAA, 0, 0, 0, 0, 0, 0, 0) && + OFFromBigEndian16(addr.sockaddr.in6.sin6_port) == 1234) + + TEST(@"Parsing an IPv6 #5", + R(addr = OFSocketAddressParseIP(@"::aaAa", 1234)) && + COMPARE_V6(addr, 0, 0, 0, 0, 0, 0, 0, 0xAAAA) && + OFFromBigEndian16(addr.sockaddr.in6.sin6_port) == 1234) + + EXPECT_EXCEPTION(@"Refusing invalid IPv6 #1", OFInvalidFormatException, + OFSocketAddressParseIP(@"1:::2", 1234)) + + EXPECT_EXCEPTION(@"Refusing invalid IPv6 #2", OFInvalidFormatException, + OFSocketAddressParseIP(@"1: ::2", 1234)) + + EXPECT_EXCEPTION(@"Refusing invalid IPv6 #3", OFInvalidFormatException, + OFSocketAddressParseIP(@"1:: :2", 1234)) + + EXPECT_EXCEPTION(@"Refusing invalid IPv6 #4", OFInvalidFormatException, + OFSocketAddressParseIP(@"1::2::3", 1234)) + + EXPECT_EXCEPTION(@"Refusing invalid IPv6 #5", OFInvalidFormatException, + OFSocketAddressParseIP(@"10000::1", 1234)) + + EXPECT_EXCEPTION(@"Refusing invalid IPv6 #6", OFInvalidFormatException, + OFSocketAddressParseIP(@"::10000", 1234)) + + EXPECT_EXCEPTION(@"Refusing invalid IPv6 #7", OFInvalidFormatException, + OFSocketAddressParseIP(@"::1::", 1234)) + + EXPECT_EXCEPTION(@"Refusing invalid IPv6 #8", OFInvalidFormatException, + OFSocketAddressParseIP(@"1:2:3:4:5:6:7:", 1234)) + + EXPECT_EXCEPTION(@"Refusing invalid IPv6 #9", OFInvalidFormatException, + OFSocketAddressParseIP(@"1:2:3:4:5:6:7::", 1234)) + + EXPECT_EXCEPTION(@"Refusing invalid IPv6 #10", OFInvalidFormatException, + OFSocketAddressParseIP(@"1:2", 1234)) + + TEST(@"Port of an IPv6 address", OFSocketAddressPort(&addr) == 1234) + + SET_V6(addr, 0, 0, 0, 0, 0, 0, 0, 0) + TEST(@"Converting an IPv6 to a string #1", + [OFSocketAddressString(&addr) isEqual: @"::"]) + + SET_V6(addr, 0, 0, 0, 0, 0, 0, 0, 1) + TEST(@"Converting an IPv6 to a string #2", + [OFSocketAddressString(&addr) isEqual: @"::1"]) + + SET_V6(addr, 1, 0, 0, 0, 0, 0, 0, 0) + TEST(@"Converting an IPv6 to a string #3", + [OFSocketAddressString(&addr) isEqual: @"1::"]) + + SET_V6(addr, + 0x1122, 0x3344, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0xDDEE, 0xFF00) + TEST(@"Converting an IPv6 to a string #4", + [OFSocketAddressString(&addr) + isEqual: @"1122:3344:5566:7788:99aa:bbcc:ddee:ff00"]) + + SET_V6(addr, 0x1122, 0x3344, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0xDDEE, 0) + TEST(@"Converting an IPv6 to a string #5", + [OFSocketAddressString(&addr) + isEqual: @"1122:3344:5566:7788:99aa:bbcc:ddee:0"]) + + SET_V6(addr, 0x1122, 0x3344, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0, 0) + TEST(@"Converting an IPv6 to a string #6", + [OFSocketAddressString(&addr) + isEqual: @"1122:3344:5566:7788:99aa:bbcc::"]) + + SET_V6(addr, 0, 0x3344, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0xDDEE, 0xFF00) + TEST(@"Converting an IPv6 to a string #7", + [OFSocketAddressString(&addr) + isEqual: @"0:3344:5566:7788:99aa:bbcc:ddee:ff00"]) + + SET_V6(addr, 0, 0, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0xDDEE, 0xFF00) + TEST(@"Converting an IPv6 to a string #8", + [OFSocketAddressString(&addr) + isEqual: @"::5566:7788:99aa:bbcc:ddee:ff00"]) + + SET_V6(addr, 0, 0, 0x5566, 0, 0, 0, 0xDDEE, 0xFF00) + TEST(@"Converting an IPv6 to a string #9", + [OFSocketAddressString(&addr) isEqual: @"0:0:5566::ddee:ff00"]) + + SET_V6(addr, 0, 0, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0, 0) + TEST(@"Converting an IPv6 to a string #10", + [OFSocketAddressString(&addr) + isEqual: @"::5566:7788:99aa:bbcc:0:0"]) + + objc_autoreleasePoolPop(pool); +} +@end Index: tests/OFStreamTests.m ================================================================== --- tests/OFStreamTests.m +++ tests/OFStreamTests.m @@ -15,19 +15,19 @@ #include "config.h" #import "TestsAppDelegate.h" -static OFString *module = @"OFStream"; +static OFString *const module = @"OFStream"; -@interface StreamTester: OFStream +@interface StreamTest: OFStream { int state; } @end -@implementation StreamTester +@implementation StreamTest - (bool)lowlevelIsAtEndOfStream { return (state > 1); } @@ -62,22 +62,25 @@ @implementation TestsAppDelegate (OFStreamTests) - (void)streamTests { void *pool = objc_autoreleasePoolPush(); size_t pageSize = [OFSystemInfo pageSize]; - StreamTester *t = [[[StreamTester alloc] init] autorelease]; - OFString *str; - char *cstr; - - cstr = OFAllocMemory(pageSize - 2, 1); - memset(cstr, 'X', pageSize - 3); - cstr[pageSize - 3] = '\0'; - - TEST(@"-[readLine]", [[t readLine] isEqual: @"foo"] && - [(str = [t readLine]) length] == pageSize - 3 && - !strcmp(str.UTF8String, cstr)) - - OFFreeMemory(cstr); + StreamTest *test = [[[StreamTest alloc] init] autorelease]; + OFString *string; + char *cString; + + cString = OFAllocMemory(pageSize - 2, 1); + memset(cString, 'X', pageSize - 3); + cString[pageSize - 3] = '\0'; + + TEST(@"-[readLine] #1", [[test readLine] isEqual: @"foo"]) + + string = [test readLine]; + TEST(@"-[readLine] #2", string != nil && + string.length == pageSize - 3 && + !strcmp(string.UTF8String, cString)) + + OFFreeMemory(cString); objc_autoreleasePoolPop(pool); } @end Index: tests/OFStringTests.m ================================================================== --- tests/OFStringTests.m +++ tests/OFStringTests.m @@ -27,26 +27,26 @@ #ifndef INFINITY # define INFINITY __builtin_inf() #endif -static OFString *module = nil; -static OFString *whitespace[] = { +static OFString *module; +static OFString *const whitespace[] = { @" \r \t\n\t \tasd \t \t\t\r\n", @" \t\t \t\t \t \t" }; -static OFUnichar ucstr[] = { +static const OFUnichar unicharString[] = { 0xFEFF, 'f', 0xF6, 0xF6, 'b', 0xE4, 'r', 0x1F03A, 0 }; -static OFUnichar sucstr[] = { +static const OFUnichar swappedUnicharString[] = { 0xFFFE0000, 0x66000000, 0xF6000000, 0xF6000000, 0x62000000, 0xE4000000, 0x72000000, 0x3AF00100, 0 }; -static uint16_t utf16str[] = { +static const OFChar16 char16String[] = { 0xFEFF, 'f', 0xF6, 0xF6, 'b', 0xE4, 'r', 0xD83C, 0xDC3A, 0 }; -static uint16_t sutf16str[] = { +static const OFChar16 swappedChar16String[] = { 0xFFFE, 0x6600, 0xF600, 0xF600, 0x6200, 0xE400, 0x7200, 0x3CD8, 0x3ADC, 0 }; @interface SimpleString: OFString @@ -211,34 +211,35 @@ @implementation TestsAppDelegate (OFStringTests) - (void)stringTestsWithClass: (Class)stringClass mutableClass: (Class)mutableStringClass { void *pool = objc_autoreleasePoolPush(); - OFMutableString *s[3]; - OFString *is; - OFArray *a; + OFMutableString *mutableString1, *mutableString2, *mutableString3; + OFString *string; + OFArray *array; size_t i; - const OFUnichar *ua; - const uint16_t *u16a; - OFCharacterSet *cs; - EntityHandler *h; + const OFUnichar *characters; + const uint16_t *UTF16Characters; + OFCharacterSet *characterSet; + EntityHandler *entityHandler; #ifdef OF_HAVE_BLOCKS __block int j; __block bool ok; #endif #define C(s) ((OFString *)[stringClass stringWithString: s]) - s[0] = [mutableStringClass stringWithString: @"täs€"]; - s[1] = [mutableStringClass string]; - s[2] = [[s[0] copy] autorelease]; - - TEST(@"-[isEqual:]", [s[0] isEqual: s[2]] && - ![s[0] isEqual: [[[OFObject alloc] init] autorelease]]) - - TEST(@"-[compare:]", [s[0] compare: s[2]] == OFOrderedSame && - [s[0] compare: @""] != OFOrderedSame && + mutableString1 = [mutableStringClass stringWithString: @"täs€"]; + mutableString2 = [mutableStringClass string]; + mutableString3 = [[mutableString1 copy] autorelease]; + + TEST(@"-[isEqual:]", [mutableString1 isEqual: mutableString3] && + ![mutableString1 isEqual: [[[OFObject alloc] init] autorelease]]) + + TEST(@"-[compare:]", + [mutableString1 compare: mutableString3] == OFOrderedSame && + [mutableString1 compare: @""] != OFOrderedSame && [C(@"") compare: @"a"] == OFOrderedAscending && [C(@"a") compare: @"b"] == OFOrderedAscending && [C(@"cd") compare: @"bc"] == OFOrderedDescending && [C(@"ä") compare: @"ö"] == OFOrderedAscending && [C(@"€") compare: @"ß"] == OFOrderedDescending && @@ -263,107 +264,114 @@ [stringClass stringWithUTF8String: "AbD"]] == [C(@"abc") compare: @"abd"]) #endif TEST(@"-[hash] is the same if -[isEqual:] is true", - s[0].hash == s[2].hash) + mutableString1.hash == mutableString3.hash) - TEST(@"-[description]", [s[0].description isEqual: s[0]]) + TEST(@"-[description]", + [mutableString1.description isEqual: mutableString1]) TEST(@"-[appendString:] and -[appendUTF8String:]", - R([s[1] appendUTF8String: "1𝄞"]) && R([s[1] appendString: @"3"]) && - R([s[0] appendString: s[1]]) && [s[0] isEqual: @"täs€1𝄞3"]) + R([mutableString2 appendUTF8String: "1𝄞"]) && + R([mutableString2 appendString: @"3"]) && + R([mutableString1 appendString: mutableString2]) && + [mutableString1 isEqual: @"täs€1𝄞3"]) TEST(@"-[appendCharacters:length:]", - R([s[1] appendCharacters: ucstr + 6 length: 2]) && - [s[1] isEqual: @"1𝄞3r🀺"]) + R([mutableString2 appendCharacters: unicharString + 6 length: 2]) && + [mutableString2 isEqual: @"1𝄞3r🀺"]) - TEST(@"-[length]", s[0].length == 7) - TEST(@"-[UTF8StringLength]", s[0].UTF8StringLength == 13) - TEST(@"-[hash]", s[0].hash == 0x705583C0) + TEST(@"-[length]", mutableString1.length == 7) + TEST(@"-[UTF8StringLength]", mutableString1.UTF8StringLength == 13) + TEST(@"-[hash]", mutableString1.hash == 0x705583C0) TEST(@"-[characterAtIndex:]", - [s[0] characterAtIndex: 0] == 't' && - [s[0] characterAtIndex: 1] == 0xE4 && - [s[0] characterAtIndex: 3] == 0x20AC && - [s[0] characterAtIndex: 5] == 0x1D11E) + [mutableString1 characterAtIndex: 0] == 't' && + [mutableString1 characterAtIndex: 1] == 0xE4 && + [mutableString1 characterAtIndex: 3] == 0x20AC && + [mutableString1 characterAtIndex: 5] == 0x1D11E) EXPECT_EXCEPTION(@"Detect out of range in -[characterAtIndex:]", - OFOutOfRangeException, [s[0] characterAtIndex: 7]) + OFOutOfRangeException, [mutableString1 characterAtIndex: 7]) - TEST(@"-[reverse]", R([s[0] reverse]) && [s[0] isEqual: @"3𝄞1€sät"]) + TEST(@"-[reverse]", + R([mutableString1 reverse]) && [mutableString1 isEqual: @"3𝄞1€sät"]) - s[1] = [mutableStringClass stringWithString: @"abc"]; + mutableString2 = [mutableStringClass stringWithString: @"abc"]; #ifdef OF_HAVE_UNICODE_TABLES - TEST(@"-[uppercase]", R([s[0] uppercase]) && - [s[0] isEqual: @"3𝄞1€SÄT"] && - R([s[1] uppercase]) && [s[1] isEqual: @"ABC"]) + TEST(@"-[uppercase]", R([mutableString1 uppercase]) && + [mutableString1 isEqual: @"3𝄞1€SÄT"] && + R([mutableString2 uppercase]) && [mutableString2 isEqual: @"ABC"]) - TEST(@"-[lowercase]", R([s[0] lowercase]) && - [s[0] isEqual: @"3𝄞1€sät"] && - R([s[1] lowercase]) && [s[1] isEqual: @"abc"]) + TEST(@"-[lowercase]", R([mutableString1 lowercase]) && + [mutableString1 isEqual: @"3𝄞1€sät"] && + R([mutableString2 lowercase]) && [mutableString2 isEqual: @"abc"]) TEST(@"-[uppercaseString]", - [[s[0] uppercaseString] isEqual: @"3𝄞1€SÄT"]) + [[mutableString1 uppercaseString] isEqual: @"3𝄞1€SÄT"]) - TEST(@"-[lowercaseString]", R([s[0] uppercase]) && - [[s[0] lowercaseString] isEqual: @"3𝄞1€sät"]) + TEST(@"-[lowercaseString]", R([mutableString1 uppercase]) && + [[mutableString1 lowercaseString] isEqual: @"3𝄞1€sät"]) TEST(@"-[capitalizedString]", [C(@"džbla tdžst TDŽST").capitalizedString isEqual: @"Džbla Tdžst Tdžst"]) #else - TEST(@"-[uppercase]", R([s[0] uppercase]) && - [s[0] isEqual: @"3𝄞1€SäT"] && - R([s[1] uppercase]) && [s[1] isEqual: @"ABC"]) - - TEST(@"-[lowercase]", R([s[0] lowercase]) && - [s[0] isEqual: @"3𝄞1€sät"] && - R([s[1] lowercase]) && [s[1] isEqual: @"abc"]) - - TEST(@"-[uppercaseString]", [s[0].uppercaseString isEqual: @"3𝄞1€SäT"]) - - TEST(@"-[lowercaseString]", R([s[0] uppercase]) && - [s[0].lowercaseString isEqual: @"3𝄞1€sät"]) + TEST(@"-[uppercase]", R([mutableString1 uppercase]) && + [mutableString1 isEqual: @"3𝄞1€SäT"] && + R([mutableString2 uppercase]) && [mutableString2 isEqual: @"ABC"]) + + TEST(@"-[lowercase]", R([mutableString1 lowercase]) && + [mutableString1 isEqual: @"3𝄞1€sät"] && + R([mutableString2 lowercase]) && [mutableString2 isEqual: @"abc"]) + + TEST(@"-[uppercaseString]", + [mutableString1.uppercaseString isEqual: @"3𝄞1€SäT"]) + + TEST(@"-[lowercaseString]", + R([mutableString1 uppercase]) && + [mutableString1.lowercaseString isEqual: @"3𝄞1€sät"]) TEST(@"-[capitalizedString]", [C(@"džbla tdžst TDŽST").capitalizedString isEqual: @"džbla Tdžst TDŽst"]) #endif TEST(@"+[stringWithUTF8String:length:]", - (s[0] = [mutableStringClass stringWithUTF8String: "\xEF\xBB\xBF" - "foobar" - length: 6]) && - [s[0] isEqual: @"foo"]) + (mutableString1 = [mutableStringClass + stringWithUTF8String: "\xEF\xBB\xBF" "foobar" + length: 6]) && + [mutableString1 isEqual: @"foo"]) TEST(@"+[stringWithUTF16String:]", - (is = [stringClass stringWithUTF16String: utf16str]) && - [is isEqual: @"fööbär🀺"] && - (is = [stringClass stringWithUTF16String: sutf16str]) && - [is isEqual: @"fööbär🀺"]) + (string = [stringClass stringWithUTF16String: char16String]) && + [string isEqual: @"fööbär🀺"] && + (string = [stringClass stringWithUTF16String: + swappedChar16String]) && [string isEqual: @"fööbär🀺"]) TEST(@"+[stringWithUTF32String:]", - (is = [stringClass stringWithUTF32String: ucstr]) && - [is isEqual: @"fööbär🀺"] && - (is = [stringClass stringWithUTF32String: sucstr]) && - [is isEqual: @"fööbär🀺"]) + (string = [stringClass stringWithUTF32String: unicharString]) && + [string isEqual: @"fööbär🀺"] && + (string = [stringClass stringWithUTF32String: + swappedUnicharString]) && [string isEqual: @"fööbär🀺"]) #ifdef OF_HAVE_FILES - TEST(@"+[stringWithContentsOfFile:encoding]", (is = [stringClass + TEST(@"+[stringWithContentsOfFile:encoding]", (string = [stringClass stringWithContentsOfFile: @"testfile.txt" encoding: OFStringEncodingISO8859_1]) && - [is isEqual: @"testäöü"]) + [string isEqual: @"testäöü"]) - TEST(@"+[stringWithContentsOfURL:encoding]", (is = [stringClass + TEST(@"+[stringWithContentsOfURL:encoding]", (string = [stringClass stringWithContentsOfURL: [OFURL fileURLWithPath: @"testfile.txt"] encoding: OFStringEncodingISO8859_1]) && - [is isEqual: @"testäöü"]) + [string isEqual: @"testäöü"]) #endif TEST(@"-[appendUTFString:length:]", - R([s[0] appendUTF8String: "\xEF\xBB\xBF" "barqux" length: 6]) && - [s[0] isEqual: @"foobar"]) + R([mutableString1 appendUTF8String: "\xEF\xBB\xBF" "barqux" + length: 6]) && + [mutableString1 isEqual: @"foobar"]) EXPECT_EXCEPTION(@"Detection of invalid UTF-8 encoding #1", OFInvalidEncodingException, [stringClass stringWithUTF8String: "\xE0\x80"]) EXPECT_EXCEPTION(@"Detection of invalid UTF-8 encoding #2", @@ -473,17 +481,18 @@ !strcmp([C(@"T€st strîng ░▒▓") lossyCStringWithEncoding: OFStringEncodingCodepage437], "T?st str\x8Cng \xB0\xB1\xB2")) #endif TEST(@"+[stringWithFormat:]", - [(s[0] = [mutableStringClass stringWithFormat: @"%@:%d", @"test", - 123]) + [(mutableString1 = [mutableStringClass stringWithFormat: @"%@:%d", + @"test", + 123]) isEqual: @"test:123"]) TEST(@"-[appendFormat:]", - R(([s[0] appendFormat: @"%02X", 15])) && - [s[0] isEqual: @"test:1230F"]) + R(([mutableString1 appendFormat: @"%02X", 15])) && + [mutableString1 isEqual: @"test:1230F"]) TEST(@"-[rangeOfString:]", [C(@"𝄞öö") rangeOfString: @"öö"].location == 1 && [C(@"𝄞öö") rangeOfString: @"ö"].location == 1 && [C(@"𝄞öö") rangeOfString: @"𝄞"].location == 0 && @@ -500,29 +509,29 @@ EXPECT_EXCEPTION( @"Detect out of range in -[rangeOfString:options:range:]", OFOutOfRangeException, [C(@"𝄞öö") rangeOfString: @"ö" options: 0 range: OFRangeMake(3, 1)]) - cs = [OFCharacterSet characterSetWithCharactersInString: @"cđ"]; + characterSet = + [OFCharacterSet characterSetWithCharactersInString: @"cđ"]; TEST(@"-[indexOfCharacterFromSet:]", - [C(@"abcđabcđe") indexOfCharacterFromSet: cs] == 2 && - [C(@"abcđabcđë") - indexOfCharacterFromSet: cs - options: OFStringSearchBackwards] == 7 && - [C(@"abcđabcđë") - indexOfCharacterFromSet: cs - options: 0 - range: OFRangeMake(4, 4)] == 6 && - [C(@"abcđabcđëf") - indexOfCharacterFromSet: cs - options: 0 - range: OFRangeMake(8, 2)] == OFNotFound) + [C(@"abcđabcđe") indexOfCharacterFromSet: characterSet] == 2 && + [C(@"abcđabcđë") + indexOfCharacterFromSet: characterSet + options: OFStringSearchBackwards] == 7 && + [C(@"abcđabcđë") indexOfCharacterFromSet: characterSet + options: 0 + range: OFRangeMake(4, 4)] == 6 && + [C(@"abcđabcđëf") + indexOfCharacterFromSet: characterSet + options: 0 + range: OFRangeMake(8, 2)] == OFNotFound) EXPECT_EXCEPTION( @"Detect out of range in -[indexOfCharacterFromSet:options:range:]", OFOutOfRangeException, - [C(@"𝄞öö") indexOfCharacterFromSet: cs + [C(@"𝄞öö") indexOfCharacterFromSet: characterSet options: 0 range: OFRangeMake(3, 1)]) TEST(@"-[substringWithRange:]", [[C(@"𝄞öö") substringWithRange: OFRangeMake(1, 1)] isEqual: @"ö"] && @@ -563,28 +572,30 @@ TEST(@"-[isAbsolutePath]", C(@"/foo").absolutePath && C(@"/foo/bar").absolutePath && !C(@"foo/bar").absolutePath && !C(@"foo").absolutePath) # endif - s[0] = [mutableStringClass stringWithString: @"foo"]; -# if defined(OF_WINDOWS) || defined(OF_MSDOS) - [s[0] appendString: @"\\"]; -# else - [s[0] appendString: @"/"]; -# endif - [s[0] appendString: @"bar"]; - s[1] = [mutableStringClass stringWithString: s[0]]; -# if defined(OF_WINDOWS) || defined(OF_MSDOS) - [s[1] appendString: @"\\"]; -# else - [s[1] appendString: @"/"]; -# endif - is = [stringClass stringWithString: s[1]]; - [s[1] appendString: @"baz"]; - TEST(@"-[stringByAppendingPathComponent:]", - [[s[0] stringByAppendingPathComponent: @"baz"] isEqual: s[1]] && - [[is stringByAppendingPathComponent: @"baz"] isEqual: s[1]]) + mutableString1 = [mutableStringClass stringWithString: @"foo"]; +# if defined(OF_WINDOWS) || defined(OF_MSDOS) + [mutableString1 appendString: @"\\"]; +# else + [mutableString1 appendString: @"/"]; +# endif + [mutableString1 appendString: @"bar"]; + mutableString2 = [mutableStringClass stringWithString: mutableString1]; +# if defined(OF_WINDOWS) || defined(OF_MSDOS) + [mutableString2 appendString: @"\\"]; +# else + [mutableString2 appendString: @"/"]; +# endif + string = [stringClass stringWithString: mutableString2]; + [mutableString2 appendString: @"baz"]; + TEST(@"-[stringByAppendingPathComponent:]", + [[mutableString1 stringByAppendingPathComponent: @"baz"] + isEqual: mutableString2] && + [[string stringByAppendingPathComponent: @"baz"] + isEqual: mutableString2]) #endif TEST(@"-[hasPrefix:]", [C(@"foobar") hasPrefix: @"foo"] && ![C(@"foobar") hasPrefix: @"foobar0"]) @@ -591,61 +602,62 @@ TEST(@"-[hasSuffix:]", [C(@"foobar") hasSuffix: @"bar"] && ![C(@"foobar") hasSuffix: @"foobar0"]) i = 0; TEST(@"-[componentsSeparatedByString:]", - (a = [C(@"fooXXbarXXXXbazXXXX") + (array = [C(@"fooXXbarXXXXbazXXXX") componentsSeparatedByString: @"XX"]) && - [[a objectAtIndex: i++] isEqual: @"foo"] && - [[a objectAtIndex: i++] isEqual: @"bar"] && - [[a objectAtIndex: i++] isEqual: @""] && - [[a objectAtIndex: i++] isEqual: @"baz"] && - [[a objectAtIndex: i++] isEqual: @""] && - [[a objectAtIndex: i++] isEqual: @""] && - a.count == i && - (a = [C(@"foo") componentsSeparatedByString: @""]) && - [[a objectAtIndex: 0] isEqual: @"foo"] && - a.count == 1) + [[array objectAtIndex: i++] isEqual: @"foo"] && + [[array objectAtIndex: i++] isEqual: @"bar"] && + [[array objectAtIndex: i++] isEqual: @""] && + [[array objectAtIndex: i++] isEqual: @"baz"] && + [[array objectAtIndex: i++] isEqual: @""] && + [[array objectAtIndex: i++] isEqual: @""] && + array.count == i && + (array = [C(@"foo") componentsSeparatedByString: @""]) && + [[array objectAtIndex: 0] isEqual: @"foo"] && + array.count == 1) i = 0; TEST(@"-[componentsSeparatedByString:options:]", - (a = [C(@"fooXXbarXXXXbazXXXX") + (array = [C(@"fooXXbarXXXXbazXXXX") componentsSeparatedByString: @"XX" options: OFStringSkipEmptyComponents]) && - [[a objectAtIndex: i++] isEqual: @"foo"] && - [[a objectAtIndex: i++] isEqual: @"bar"] && - [[a objectAtIndex: i++] isEqual: @"baz"] && - a.count == i) + [[array objectAtIndex: i++] isEqual: @"foo"] && + [[array objectAtIndex: i++] isEqual: @"bar"] && + [[array objectAtIndex: i++] isEqual: @"baz"] && + array.count == i) - cs = [OFCharacterSet characterSetWithCharactersInString: @"XYZ"]; + characterSet = + [OFCharacterSet characterSetWithCharactersInString: @"XYZ"]; i = 0; TEST(@"-[componentsSeparatedByCharactersInSet:]", - (a = [C(@"fooXYbarXYZXbazXYXZx") - componentsSeparatedByCharactersInSet: cs]) && - [[a objectAtIndex: i++] isEqual: @"foo"] && - [[a objectAtIndex: i++] isEqual: @""] && - [[a objectAtIndex: i++] isEqual: @"bar"] && - [[a objectAtIndex: i++] isEqual: @""] && - [[a objectAtIndex: i++] isEqual: @""] && - [[a objectAtIndex: i++] isEqual: @""] && - [[a objectAtIndex: i++] isEqual: @"baz"] && - [[a objectAtIndex: i++] isEqual: @""] && - [[a objectAtIndex: i++] isEqual: @""] && - [[a objectAtIndex: i++] isEqual: @""] && - [[a objectAtIndex: i++] isEqual: @"x"] && - a.count == i) + (array = [C(@"fooXYbarXYZXbazXYXZx") + componentsSeparatedByCharactersInSet: characterSet]) && + [[array objectAtIndex: i++] isEqual: @"foo"] && + [[array objectAtIndex: i++] isEqual: @""] && + [[array objectAtIndex: i++] isEqual: @"bar"] && + [[array objectAtIndex: i++] isEqual: @""] && + [[array objectAtIndex: i++] isEqual: @""] && + [[array objectAtIndex: i++] isEqual: @""] && + [[array objectAtIndex: i++] isEqual: @"baz"] && + [[array objectAtIndex: i++] isEqual: @""] && + [[array objectAtIndex: i++] isEqual: @""] && + [[array objectAtIndex: i++] isEqual: @""] && + [[array objectAtIndex: i++] isEqual: @"x"] && + array.count == i) i = 0; TEST(@"-[componentsSeparatedByCharactersInSet:options:]", - (a = [C(@"fooXYbarXYZXbazXYXZ") - componentsSeparatedByCharactersInSet: cs + (array = [C(@"fooXYbarXYZXbazXYXZ") + componentsSeparatedByCharactersInSet: characterSet options: OFStringSkipEmptyComponents]) && - [[a objectAtIndex: i++] isEqual: @"foo"] && - [[a objectAtIndex: i++] isEqual: @"bar"] && - [[a objectAtIndex: i++] isEqual: @"baz"] && - a.count == i) + [[array objectAtIndex: i++] isEqual: @"foo"] && + [[array objectAtIndex: i++] isEqual: @"bar"] && + [[array objectAtIndex: i++] isEqual: @"baz"] && + array.count == i) #ifdef OF_HAVE_FILES # if defined(OF_WINDOWS) TEST(@"+[pathWithComponents:]", [[stringClass pathWithComponents: [OFArray arrayWithObjects: @@ -746,151 +758,151 @@ # endif # if defined(OF_WINDOWS) TEST(@"-[pathComponents]", /* c:/tmp */ - (a = C(@"c:/tmp").pathComponents) && a.count == 2 && - [[a objectAtIndex: 0] isEqual: @"c:/"] && - [[a objectAtIndex: 1] isEqual: @"tmp"] && + (array = C(@"c:/tmp").pathComponents) && array.count == 2 && + [[array objectAtIndex: 0] isEqual: @"c:/"] && + [[array objectAtIndex: 1] isEqual: @"tmp"] && /* c:\tmp\ */ - (a = C(@"c:\\tmp\\").pathComponents) && a.count == 2 && - [[a objectAtIndex: 0] isEqual: @"c:\\"] && - [[a objectAtIndex: 1] isEqual: @"tmp"] && + (array = C(@"c:\\tmp\\").pathComponents) && array.count == 2 && + [[array objectAtIndex: 0] isEqual: @"c:\\"] && + [[array objectAtIndex: 1] isEqual: @"tmp"] && /* c:\ */ - (a = C(@"c:\\").pathComponents) && a.count == 1 && - [[a objectAtIndex: 0] isEqual: @"c:\\"] && + (array = C(@"c:\\").pathComponents) && array.count == 1 && + [[array objectAtIndex: 0] isEqual: @"c:\\"] && /* c:/ */ - (a = C(@"c:/").pathComponents) && a.count == 1 && - [[a objectAtIndex: 0] isEqual: @"c:/"] && + (array = C(@"c:/").pathComponents) && array.count == 1 && + [[array objectAtIndex: 0] isEqual: @"c:/"] && /* c: */ - (a = C(@"c:").pathComponents) && a.count == 1 && - [[a objectAtIndex: 0] isEqual: @"c:"] && + (array = C(@"c:").pathComponents) && array.count == 1 && + [[array objectAtIndex: 0] isEqual: @"c:"] && /* foo\bar */ - (a = C(@"foo\\bar").pathComponents) && a.count == 2 && - [[a objectAtIndex: 0] isEqual: @"foo"] && - [[a objectAtIndex: 1] isEqual: @"bar"] && + (array = C(@"foo\\bar").pathComponents) && array.count == 2 && + [[array objectAtIndex: 0] isEqual: @"foo"] && + [[array objectAtIndex: 1] isEqual: @"bar"] && /* foo\bar/baz/ */ - (a = C(@"foo\\bar/baz/").pathComponents) && a.count == 3 && - [[a objectAtIndex: 0] isEqual: @"foo"] && - [[a objectAtIndex: 1] isEqual: @"bar"] && - [[a objectAtIndex: 2] isEqual: @"baz"] && + (array = C(@"foo\\bar/baz/").pathComponents) && array.count == 3 && + [[array objectAtIndex: 0] isEqual: @"foo"] && + [[array objectAtIndex: 1] isEqual: @"bar"] && + [[array objectAtIndex: 2] isEqual: @"baz"] && /* foo\/ */ - (a = C(@"foo\\/").pathComponents) && a.count == 1 && - [[a objectAtIndex: 0] isEqual: @"foo"] && + (array = C(@"foo\\/").pathComponents) && array.count == 1 && + [[array objectAtIndex: 0] isEqual: @"foo"] && /* \\foo\bar */ - (a = C(@"\\\\foo\\bar").pathComponents) && a.count == 3 && - [[a objectAtIndex: 0] isEqual: @"\\\\"] && - [[a objectAtIndex: 1] isEqual: @"foo"] && - [[a objectAtIndex: 2] isEqual: @"bar"] && + (array = C(@"\\\\foo\\bar").pathComponents) && array.count == 3 && + [[array objectAtIndex: 0] isEqual: @"\\\\"] && + [[array objectAtIndex: 1] isEqual: @"foo"] && + [[array objectAtIndex: 2] isEqual: @"bar"] && C(@"").pathComponents.count == 0) # elif defined(OF_MSDOS) TEST(@"-[pathComponents]", /* c:/tmp */ - (a = C(@"c:/tmp").pathComponents) && a.count == 2 && - [[a objectAtIndex: 0] isEqual: @"c:/"] && - [[a objectAtIndex: 1] isEqual: @"tmp"] && + (array = C(@"c:/tmp").pathComponents) && array.count == 2 && + [[array objectAtIndex: 0] isEqual: @"c:/"] && + [[array objectAtIndex: 1] isEqual: @"tmp"] && /* c:\tmp\ */ - (a = C(@"c:\\tmp\\").pathComponents) && a.count == 2 && - [[a objectAtIndex: 0] isEqual: @"c:\\"] && - [[a objectAtIndex: 1] isEqual: @"tmp"] && + (array = C(@"c:\\tmp\\").pathComponents) && array.count == 2 && + [[array objectAtIndex: 0] isEqual: @"c:\\"] && + [[array objectAtIndex: 1] isEqual: @"tmp"] && /* c:\ */ - (a = C(@"c:\\").pathComponents) && a.count == 1 && - [[a objectAtIndex: 0] isEqual: @"c:\\"] && + (array = C(@"c:\\").pathComponents) && array.count == 1 && + [[array objectAtIndex: 0] isEqual: @"c:\\"] && /* c:/ */ - (a = C(@"c:/").pathComponents) && a.count == 1 && - [[a objectAtIndex: 0] isEqual: @"c:/"] && + (array = C(@"c:/").pathComponents) && array.count == 1 && + [[array objectAtIndex: 0] isEqual: @"c:/"] && /* c: */ - (a = C(@"c:").pathComponents) && a.count == 1 && - [[a objectAtIndex: 0] isEqual: @"c:"] && + (array = C(@"c:").pathComponents) && array.count == 1 && + [[array objectAtIndex: 0] isEqual: @"c:"] && /* foo\bar */ - (a = C(@"foo\\bar").pathComponents) && a.count == 2 && - [[a objectAtIndex: 0] isEqual: @"foo"] && - [[a objectAtIndex: 1] isEqual: @"bar"] && + (array = C(@"foo\\bar").pathComponents) && array.count == 2 && + [[array objectAtIndex: 0] isEqual: @"foo"] && + [[array objectAtIndex: 1] isEqual: @"bar"] && /* foo\bar/baz/ */ - (a = C(@"foo\\bar/baz/").pathComponents) && a.count == 3 && - [[a objectAtIndex: 0] isEqual: @"foo"] && - [[a objectAtIndex: 1] isEqual: @"bar"] && - [[a objectAtIndex: 2] isEqual: @"baz"] && + (array = C(@"foo\\bar/baz/").pathComponents) && array.count == 3 && + [[array objectAtIndex: 0] isEqual: @"foo"] && + [[array objectAtIndex: 1] isEqual: @"bar"] && + [[array objectAtIndex: 2] isEqual: @"baz"] && /* foo\/ */ - (a = C(@"foo\\/").pathComponents) && a.count == 1 && - [[a objectAtIndex: 0] isEqual: @"foo"] && + (array = C(@"foo\\/").pathComponents) && array.count == 1 && + [[array objectAtIndex: 0] isEqual: @"foo"] && C(@"").pathComponents.count == 0) # elif defined(OF_AMIGAOS) TEST(@"-[pathComponents]", /* dh0:tmp */ - (a = C(@"dh0:tmp").pathComponents) && a.count == 2 && - [[a objectAtIndex: 0] isEqual: @"dh0:"] && - [[a objectAtIndex: 1] isEqual: @"tmp"] && + (array = C(@"dh0:tmp").pathComponents) && array.count == 2 && + [[array objectAtIndex: 0] isEqual: @"dh0:"] && + [[array objectAtIndex: 1] isEqual: @"tmp"] && /* dh0:tmp/ */ - (a = C(@"dh0:tmp/").pathComponents) && a.count == 2 && - [[a objectAtIndex: 0] isEqual: @"dh0:"] && - [[a objectAtIndex: 1] isEqual: @"tmp"] && + (array = C(@"dh0:tmp/").pathComponents) && array.count == 2 && + [[array objectAtIndex: 0] isEqual: @"dh0:"] && + [[array objectAtIndex: 1] isEqual: @"tmp"] && /* dh0: */ - (a = C(@"dh0:/").pathComponents) && a.count == 2 && - [[a objectAtIndex: 0] isEqual: @"dh0:"] && - [[a objectAtIndex: 1] isEqual: @"/"] && + (array = C(@"dh0:/").pathComponents) && array.count == 2 && + [[array objectAtIndex: 0] isEqual: @"dh0:"] && + [[array objectAtIndex: 1] isEqual: @"/"] && /* foo/bar */ - (a = C(@"foo/bar").pathComponents) && a.count == 2 && - [[a objectAtIndex: 0] isEqual: @"foo"] && - [[a objectAtIndex: 1] isEqual: @"bar"] && + (array = C(@"foo/bar").pathComponents) && array.count == 2 && + [[array objectAtIndex: 0] isEqual: @"foo"] && + [[array objectAtIndex: 1] isEqual: @"bar"] && /* foo/bar/baz/ */ - (a = C(@"foo/bar/baz/").pathComponents) && a.count == 3 && - [[a objectAtIndex: 0] isEqual: @"foo"] && - [[a objectAtIndex: 1] isEqual: @"bar"] && - [[a objectAtIndex: 2] isEqual: @"baz"] && + (array = C(@"foo/bar/baz/").pathComponents) && array.count == 3 && + [[array objectAtIndex: 0] isEqual: @"foo"] && + [[array objectAtIndex: 1] isEqual: @"bar"] && + [[array objectAtIndex: 2] isEqual: @"baz"] && /* foo// */ - (a = C(@"foo//").pathComponents) && a.count == 2 && - [[a objectAtIndex: 0] isEqual: @"foo"] && - [[a objectAtIndex: 1] isEqual: @"/"] && + (array = C(@"foo//").pathComponents) && array.count == 2 && + [[array objectAtIndex: 0] isEqual: @"foo"] && + [[array objectAtIndex: 1] isEqual: @"/"] && C(@"").pathComponents.count == 0) # elif defined(OF_NINTENDO_3DS) || defined(OF_WII) TEST(@"-[pathComponents]", /* sdmc:/tmp */ - (a = C(@"sdmc:/tmp").pathComponents) && a.count == 2 && - [[a objectAtIndex: 0] isEqual: @"sdmc:"] && - [[a objectAtIndex: 1] isEqual: @"tmp"] && + (array = C(@"sdmc:/tmp").pathComponents) && array.count == 2 && + [[array objectAtIndex: 0] isEqual: @"sdmc:"] && + [[array objectAtIndex: 1] isEqual: @"tmp"] && /* sdmc:/ */ - (a = C(@"sdmc:/").pathComponents) && a.count == 1 && - [[a objectAtIndex: 0] isEqual: @"sdmc:"] && + (array = C(@"sdmc:/").pathComponents) && array.count == 1 && + [[array objectAtIndex: 0] isEqual: @"sdmc:"] && /* foo/bar */ - (a = C(@"foo/bar").pathComponents) && a.count == 2 && - [[a objectAtIndex: 0] isEqual: @"foo"] && - [[a objectAtIndex: 1] isEqual: @"bar"] && + (array = C(@"foo/bar").pathComponents) && array.count == 2 && + [[array objectAtIndex: 0] isEqual: @"foo"] && + [[array objectAtIndex: 1] isEqual: @"bar"] && /* foo/bar/baz/ */ - (a = C(@"foo/bar/baz/").pathComponents) && a.count == 3 && - [[a objectAtIndex: 0] isEqual: @"foo"] && - [[a objectAtIndex: 1] isEqual: @"bar"] && - [[a objectAtIndex: 2] isEqual: @"baz"] && + (array = C(@"foo/bar/baz/").pathComponents) && array.count == 3 && + [[array objectAtIndex: 0] isEqual: @"foo"] && + [[array objectAtIndex: 1] isEqual: @"bar"] && + [[array objectAtIndex: 2] isEqual: @"baz"] && /* foo// */ - (a = C(@"foo//").pathComponents) && a.count == 1 && - [[a objectAtIndex: 0] isEqual: @"foo"] && + (array = C(@"foo//").pathComponents) && array.count == 1 && + [[array objectAtIndex: 0] isEqual: @"foo"] && C(@"").pathComponents.count == 0) # else TEST(@"-[pathComponents]", /* /tmp */ - (a = C(@"/tmp").pathComponents) && a.count == 2 && - [[a objectAtIndex: 0] isEqual: @"/"] && - [[a objectAtIndex: 1] isEqual: @"tmp"] && + (array = C(@"/tmp").pathComponents) && array.count == 2 && + [[array objectAtIndex: 0] isEqual: @"/"] && + [[array objectAtIndex: 1] isEqual: @"tmp"] && /* /tmp/ */ - (a = C(@"/tmp/").pathComponents) && a.count == 2 && - [[a objectAtIndex: 0] isEqual: @"/"] && - [[a objectAtIndex: 1] isEqual: @"tmp"] && + (array = C(@"/tmp/").pathComponents) && array.count == 2 && + [[array objectAtIndex: 0] isEqual: @"/"] && + [[array objectAtIndex: 1] isEqual: @"tmp"] && /* / */ - (a = C(@"/").pathComponents) && a.count == 1 && - [[a objectAtIndex: 0] isEqual: @"/"] && + (array = C(@"/").pathComponents) && array.count == 1 && + [[array objectAtIndex: 0] isEqual: @"/"] && /* foo/bar */ - (a = C(@"foo/bar").pathComponents) && a.count == 2 && - [[a objectAtIndex: 0] isEqual: @"foo"] && - [[a objectAtIndex: 1] isEqual: @"bar"] && + (array = C(@"foo/bar").pathComponents) && array.count == 2 && + [[array objectAtIndex: 0] isEqual: @"foo"] && + [[array objectAtIndex: 1] isEqual: @"bar"] && /* foo/bar/baz/ */ - (a = C(@"foo/bar/baz/").pathComponents) && a.count == 3 && - [[a objectAtIndex: 0] isEqual: @"foo"] && - [[a objectAtIndex: 1] isEqual: @"bar"] && - [[a objectAtIndex: 2] isEqual: @"baz"] && + (array = C(@"foo/bar/baz/").pathComponents) && array.count == 3 && + [[array objectAtIndex: 0] isEqual: @"foo"] && + [[array objectAtIndex: 1] isEqual: @"bar"] && + [[array objectAtIndex: 2] isEqual: @"baz"] && /* foo// */ - (a = C(@"foo//").pathComponents) && a.count == 1 && - [[a objectAtIndex: 0] isEqual: @"foo"] && + (array = C(@"foo//").pathComponents) && array.count == 1 && + [[array objectAtIndex: 0] isEqual: @"foo"] && C(@"").pathComponents.count == 0) # endif # if defined(OF_WINDOWS) TEST(@"-[lastPathComponent]", @@ -1183,32 +1195,36 @@ OFOutOfRangeException, [C(@"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF" @"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF") unsignedLongLongValueWithBase: 16]) - TEST(@"-[characters]", (ua = C(@"fööbär🀺").characters) && - !memcmp(ua, ucstr + 1, sizeof(ucstr) - 8)) + TEST(@"-[characters]", (characters = C(@"fööbär🀺").characters) && + !memcmp(characters, unicharString + 1, sizeof(unicharString) - 8)) #ifdef OF_BIG_ENDIAN -# define SWAPPED_BYTE_ORDER OFByteOrderLittleEndian +# define swappedByteOrder OFByteOrderLittleEndian #else -# define SWAPPED_BYTE_ORDER OFByteOrderBigEndian +# define swappedByteOrder OFByteOrderBigEndian #endif - TEST(@"-[UTF16String]", (u16a = C(@"fööbär🀺").UTF16String) && - !memcmp(u16a, utf16str + 1, OFUTF16StringLength(utf16str) * 2) && - (u16a = [C(@"fööbär🀺") - UTF16StringWithByteOrder: SWAPPED_BYTE_ORDER]) && - !memcmp(u16a, sutf16str + 1, OFUTF16StringLength(sutf16str) * 2)) + TEST(@"-[UTF16String]", (UTF16Characters = C(@"fööbär🀺").UTF16String) && + !memcmp(UTF16Characters, char16String + 1, + OFUTF16StringLength(char16String) * 2) && + (UTF16Characters = [C(@"fööbär🀺") + UTF16StringWithByteOrder: swappedByteOrder]) && + !memcmp(UTF16Characters, swappedChar16String + 1, + OFUTF16StringLength(swappedChar16String) * 2)) TEST(@"-[UTF16StringLength]", C(@"fööbär🀺").UTF16StringLength == 8) - TEST(@"-[UTF32String]", (ua = C(@"fööbär🀺").UTF32String) && - !memcmp(ua, ucstr + 1, OFUTF32StringLength(ucstr) * 4) && - (ua = [C(@"fööbär🀺") UTF32StringWithByteOrder: - SWAPPED_BYTE_ORDER]) && - !memcmp(ua, sucstr + 1, OFUTF32StringLength(sucstr) * 4)) -#undef SWAPPED_BYTE_ORDER + TEST(@"-[UTF32String]", (characters = C(@"fööbär🀺").UTF32String) && + !memcmp(characters, unicharString + 1, + OFUTF32StringLength(unicharString) * 4) && + (characters = [C(@"fööbär🀺") UTF32StringWithByteOrder: + swappedByteOrder]) && + !memcmp(characters, swappedUnicharString + 1, + OFUTF32StringLength(swappedUnicharString) * 4)) +#undef swappedByteOrder TEST(@"-[stringByMD5Hashing]", [C(@"asdfoobar").stringByMD5Hashing isEqual: @"184dce2ec49b5422c7cfd8728864db4c"]) TEST(@"-[stringByRIPEMD160Hashing]", @@ -1233,118 +1249,138 @@ TEST(@"-[stringBySHA512Hashing]", [C(@"asdfoobar").stringBySHA512Hashing isEqual: @"0464c427da158b02161bb44a3090bbfc594611ef6a53603640454b56" @"412a9247c3579a329e53a5dc74676b106755e3394f9454a2d4227324" @"2615d32f80437d61"]) - cs = [OFCharacterSet characterSetWithCharactersInString: @"abfo'_~$🍏"]; + characterSet = + [OFCharacterSet characterSetWithCharactersInString: @"abfo'_~$🍏"]; TEST(@"-[stringByURLEncodingWithAllowedCharacters:]", [[C(@"foo\"ba'_~$]🍏🍌") stringByURLEncodingWithAllowedCharacters: - cs] isEqual: @"foo%22ba'_~$%5D🍏%F0%9F%8D%8C"]) + characterSet] isEqual: @"foo%22ba'_~$%5D🍏%F0%9F%8D%8C"]) TEST(@"-[stringByURLDecoding]", [C(@"foo%20bar%22+%24%F0%9F%8D%8C").stringByURLDecoding isEqual: @"foo bar\"+$🍌"]) TEST(@"-[insertString:atIndex:]", - (s[0] = [mutableStringClass stringWithString: @"𝄞öööbä€"]) && - R([s[0] insertString: @"äöü" atIndex: 3]) && - [s[0] isEqual: @"𝄞ööäöüöbä€"]) + (mutableString1 = [mutableStringClass + stringWithString: @"𝄞öööbä€"]) && + R([mutableString1 insertString: @"äöü" atIndex: 3]) && + [mutableString1 isEqual: @"𝄞ööäöüöbä€"]) EXPECT_EXCEPTION(@"Detect invalid format in -[stringByURLDecoding] " @"#1", OFInvalidFormatException, [C(@"foo%xbar") stringByURLDecoding]) EXPECT_EXCEPTION(@"Detect invalid encoding in -[stringByURLDecoding] " @"#2", OFInvalidEncodingException, [C(@"foo%FFbar") stringByURLDecoding]) TEST(@"-[setCharacter:atIndex:]", - (s[0] = [mutableStringClass stringWithString: @"abäde"]) && - R([s[0] setCharacter: 0xF6 atIndex: 2]) && - [s[0] isEqual: @"aböde"] && - R([s[0] setCharacter: 'c' atIndex: 2]) && - [s[0] isEqual: @"abcde"] && - R([s[0] setCharacter: 0x20AC atIndex: 3]) && - [s[0] isEqual: @"abc€e"] && - R([s[0] setCharacter: 'x' atIndex: 1]) && [s[0] isEqual: @"axc€e"]) + (mutableString1 = [mutableStringClass + stringWithString: @"abäde"]) && + R([mutableString1 setCharacter: 0xF6 atIndex: 2]) && + [mutableString1 isEqual: @"aböde"] && + R([mutableString1 setCharacter: 'c' atIndex: 2]) && + [mutableString1 isEqual: @"abcde"] && + R([mutableString1 setCharacter: 0x20AC atIndex: 3]) && + [mutableString1 isEqual: @"abc€e"] && + R([mutableString1 setCharacter: 'x' atIndex: 1]) && + [mutableString1 isEqual: @"axc€e"]) TEST(@"-[deleteCharactersInRange:]", - (s[0] = [mutableStringClass stringWithString: @"𝄞öööbä€"]) && - R([s[0] deleteCharactersInRange: OFRangeMake(1, 3)]) && - [s[0] isEqual: @"𝄞bä€"] && - R([s[0] deleteCharactersInRange: OFRangeMake(0, 4)]) && - [s[0] isEqual: @""]) + (mutableString1 = [mutableStringClass + stringWithString: @"𝄞öööbä€"]) && + R([mutableString1 deleteCharactersInRange: OFRangeMake(1, 3)]) && + [mutableString1 isEqual: @"𝄞bä€"] && + R([mutableString1 deleteCharactersInRange: OFRangeMake(0, 4)]) && + [mutableString1 isEqual: @""]) TEST(@"-[replaceCharactersInRange:withString:]", - (s[0] = [mutableStringClass stringWithString: @"𝄞öööbä€"]) && - R([s[0] replaceCharactersInRange: OFRangeMake(1, 3) - withString: @"äöüß"]) && - [s[0] isEqual: @"𝄞äöüßbä€"] && - R([s[0] replaceCharactersInRange: OFRangeMake(4, 2) - withString: @"b"]) && - [s[0] isEqual: @"𝄞äöübä€"] && - R([s[0] replaceCharactersInRange: OFRangeMake(0, 7) - withString: @""]) && - [s[0] isEqual: @""]) + (mutableString1 = [mutableStringClass + stringWithString: @"𝄞öööbä€"]) && + R([mutableString1 replaceCharactersInRange: OFRangeMake(1, 3) + withString: @"äöüß"]) && + [mutableString1 isEqual: @"𝄞äöüßbä€"] && + R([mutableString1 replaceCharactersInRange: OFRangeMake(4, 2) + withString: @"b"]) && + [mutableString1 isEqual: @"𝄞äöübä€"] && + R([mutableString1 replaceCharactersInRange: OFRangeMake(0, 7) + withString: @""]) && + [mutableString1 isEqual: @""]) EXPECT_EXCEPTION(@"Detect OoR in -[deleteCharactersInRange:] #1", OFOutOfRangeException, { - s[0] = [mutableStringClass stringWithString: @"𝄞öö"]; - [s[0] deleteCharactersInRange: OFRangeMake(2, 2)]; + mutableString1 = [mutableStringClass stringWithString: @"𝄞öö"]; + [mutableString1 deleteCharactersInRange: OFRangeMake(2, 2)]; }) EXPECT_EXCEPTION(@"Detect OoR in -[deleteCharactersInRange:] #2", OFOutOfRangeException, - [s[0] deleteCharactersInRange: OFRangeMake(4, 0)]) + [mutableString1 deleteCharactersInRange: OFRangeMake(4, 0)]) EXPECT_EXCEPTION(@"Detect OoR in " @"-[replaceCharactersInRange:withString:] #1", OFOutOfRangeException, - [s[0] replaceCharactersInRange: OFRangeMake(2, 2) withString: @""]) + [mutableString1 replaceCharactersInRange: OFRangeMake(2, 2) + withString: @""]) EXPECT_EXCEPTION(@"Detect OoR in " @"-[replaceCharactersInRange:withString:] #2", OFOutOfRangeException, - [s[0] replaceCharactersInRange: OFRangeMake(4, 0) withString: @""]) + [mutableString1 replaceCharactersInRange: OFRangeMake(4, 0) + withString: @""]) TEST(@"-[replaceOccurrencesOfString:withString:]", - (s[0] = [mutableStringClass stringWithString: + (mutableString1 = [mutableStringClass stringWithString: @"asd fo asd fofo asd"]) && - R([s[0] replaceOccurrencesOfString: @"fo" withString: @"foo"]) && - [s[0] isEqual: @"asd foo asd foofoo asd"] && - (s[0] = [mutableStringClass stringWithString: @"XX"]) && - R([s[0] replaceOccurrencesOfString: @"X" withString: @"XX"]) && - [s[0] isEqual: @"XXXX"]) + R([mutableString1 replaceOccurrencesOfString: @"fo" + withString: @"foo"]) && + [mutableString1 isEqual: @"asd foo asd foofoo asd"] && + (mutableString1 = [mutableStringClass stringWithString: @"XX"]) && + R([mutableString1 replaceOccurrencesOfString: @"X" + withString: @"XX"]) && + [mutableString1 isEqual: @"XXXX"]) TEST(@"-[replaceOccurrencesOfString:withString:options:range:]", - (s[0] = [mutableStringClass stringWithString: - @"foofoobarfoobarfoo"]) && - R([s[0] replaceOccurrencesOfString: @"oo" - withString: @"óò" - options: 0 - range: OFRangeMake(2, 15)]) && - [s[0] isEqual: @"foofóòbarfóòbarfoo"]) + (mutableString1 = [mutableStringClass stringWithString: + @"foofoobarfoobarfoo"]) && R([mutableString1 + replaceOccurrencesOfString: @"oo" + withString: @"óò" + options: 0 + range: OFRangeMake(2, 15)]) && + [mutableString1 isEqual: @"foofóòbarfóòbarfoo"]) TEST(@"-[deleteLeadingWhitespaces]", - (s[0] = [mutableStringClass stringWithString: whitespace[0]]) && - R([s[0] deleteLeadingWhitespaces]) && - [s[0] isEqual: @"asd \t \t\t\r\n"] && - (s[0] = [mutableStringClass stringWithString: whitespace[1]]) && - R([s[0] deleteLeadingWhitespaces]) && [s[0] isEqual: @""]) + (mutableString1 = [mutableStringClass + stringWithString: whitespace[0]]) && + R([mutableString1 deleteLeadingWhitespaces]) && + [mutableString1 isEqual: @"asd \t \t\t\r\n"] && + (mutableString1 = [mutableStringClass + stringWithString: whitespace[1]]) && + R([mutableString1 deleteLeadingWhitespaces]) && + [mutableString1 isEqual: @""]) TEST(@"-[deleteTrailingWhitespaces]", - (s[0] = [mutableStringClass stringWithString: whitespace[0]]) && - R([s[0] deleteTrailingWhitespaces]) && - [s[0] isEqual: @" \r \t\n\t \tasd"] && - (s[0] = [mutableStringClass stringWithString: whitespace[1]]) && - R([s[0] deleteTrailingWhitespaces]) && [s[0] isEqual: @""]) + (mutableString1 = [mutableStringClass + stringWithString: whitespace[0]]) && + R([mutableString1 deleteTrailingWhitespaces]) && + [mutableString1 isEqual: @" \r \t\n\t \tasd"] && + (mutableString1 = [mutableStringClass + stringWithString: whitespace[1]]) && + R([mutableString1 deleteTrailingWhitespaces]) && + [mutableString1 isEqual: @""]) TEST(@"-[deleteEnclosingWhitespaces]", - (s[0] = [mutableStringClass stringWithString: whitespace[0]]) && - R([s[0] deleteEnclosingWhitespaces]) && [s[0] isEqual: @"asd"] && - (s[0] = [mutableStringClass stringWithString: whitespace[1]]) && - R([s[0] deleteEnclosingWhitespaces]) && [s[0] isEqual: @""]) + (mutableString1 = [mutableStringClass + stringWithString: whitespace[0]]) && + R([mutableString1 deleteEnclosingWhitespaces]) && + [mutableString1 isEqual: @"asd"] && + (mutableString1 = [mutableStringClass + stringWithString: whitespace[1]]) && + R([mutableString1 deleteEnclosingWhitespaces]) && + [mutableString1 isEqual: @""]) #ifdef OF_HAVE_UNICODE_TABLES TEST(@"-[decomposedStringWithCanonicalMapping]", [C(@"H\xC3\xA4llj\xC3\xB6").decomposedStringWithCanonicalMapping isEqual: @"H\x61\xCC\x88llj\x6F\xCC\x88"]); @@ -1353,15 +1389,15 @@ [C(@"H\xC3\xA4llj\xC3\xB6").decomposedStringWithCompatibilityMapping isEqual: @"H\x61\xCC\x88llj\x6F\xCC\x88"]); #endif TEST(@"-[stringByXMLEscaping]", - (is = C(@" &world'\"!&").stringByXMLEscaping) && - [is isEqual: @"<hello> &world'"!&"]) + (string = C(@" &world'\"!&").stringByXMLEscaping) && + [string isEqual: @"<hello> &world'"!&"]) TEST(@"-[stringByXMLUnescaping]", - [is.stringByXMLUnescaping isEqual: @" &world'\"!&"] && + [string.stringByXMLUnescaping isEqual: @" &world'\"!&"] && [C(@"y").stringByXMLUnescaping isEqual: @"y"] && [C(@"ä").stringByXMLUnescaping isEqual: @"ä"] && [C(@"€").stringByXMLUnescaping isEqual: @"€"] && [C(@"𝄞").stringByXMLUnescaping isEqual: @"𝄞"]) @@ -1379,18 +1415,18 @@ EXPECT_EXCEPTION(@"Detect invalid entities in -[stringByXMLUnescaping] " @"#5", OFInvalidFormatException, [C(@"&#xg;") stringByXMLUnescaping]) TEST(@"-[stringByXMLUnescapingWithDelegate:]", - (h = [[[EntityHandler alloc] init] autorelease]) && - [[C(@"x&foo;y") stringByXMLUnescapingWithDelegate: h] + (entityHandler = [[[EntityHandler alloc] init] autorelease]) && + [[C(@"x&foo;y") stringByXMLUnescapingWithDelegate: entityHandler] isEqual: @"xbary"]) #ifdef OF_HAVE_BLOCKS TEST(@"-[stringByXMLUnescapingWithBlock:]", [[C(@"x&foo;y") stringByXMLUnescapingWithBlock: - ^ OFString *(OFString *str, OFString *entity) { + ^ OFString *(OFString *str, OFString *entity) { if ([entity isEqual: @"foo"]) return @"bar"; return nil; }] isEqual: @"xbary"]) Index: tests/OFTCPSocketTests.m ================================================================== --- tests/OFTCPSocketTests.m +++ tests/OFTCPSocketTests.m @@ -17,19 +17,19 @@ #include #import "TestsAppDelegate.h" -static OFString *module = @"OFTCPSocket"; +static OFString *const module = @"OFTCPSocket"; @implementation TestsAppDelegate (OFTCPSocketTests) - (void)TCPSocketTests { void *pool = objc_autoreleasePoolPush(); OFTCPSocket *server, *client = nil, *accepted; uint16_t port; - char buf[6]; + char buffer[6]; TEST(@"+[socket]", (server = [OFTCPSocket socket]) && (client = [OFTCPSocket socket])) TEST(@"-[bindToHost:port:]", @@ -47,11 +47,11 @@ isEqual: @"127.0.0.1"]) TEST(@"-[writeString:]", [client writeString: @"Hello!"]) TEST(@"-[readIntoBuffer:length:]", - [accepted readIntoBuffer: buf length: 6] && - !memcmp(buf, "Hello!", 6)) + [accepted readIntoBuffer: buffer length: 6] && + !memcmp(buffer, "Hello!", 6)) objc_autoreleasePoolPop(pool); } @end Index: tests/OFThreadTests.m ================================================================== --- tests/OFThreadTests.m +++ tests/OFThreadTests.m @@ -15,38 +15,39 @@ #include "config.h" #import "TestsAppDelegate.h" -static OFString *module = @"OFThread"; +static OFString *const module = @"OFThread"; @interface TestThread: OFThread @end @implementation TestThread - (id)main { [[OFThread threadDictionary] setObject: @"bar" forKey: @"foo"]; + OFEnsure([[[OFThread threadDictionary] + objectForKey: @"foo"] isEqual: @"bar"]); return @"success"; } @end @implementation TestsAppDelegate (OFThreadTests) - (void)threadTests { void *pool = objc_autoreleasePoolPush(); - TestThread *t; - OFMutableDictionary *d; - - TEST(@"+[thread]", (t = [TestThread thread])) - - TEST(@"-[start]", R([t start])) - - TEST(@"-[join]", [[t join] isEqual: @"success"]) - - TEST(@"-[threadDictionary]", (d = [OFThread threadDictionary]) && - [d objectForKey: @"foo"] == nil) + TestThread *thread; + + TEST(@"+[thread]", (thread = [TestThread thread])) + + TEST(@"-[start]", R([thread start])) + + TEST(@"-[join]", [[thread join] isEqual: @"success"]) + + TEST(@"-[threadDictionary]", + [[OFThread threadDictionary] objectForKey: @"foo"] == nil) objc_autoreleasePoolPop(pool); } @end Index: tests/OFUDPSocketTests.m ================================================================== --- tests/OFUDPSocketTests.m +++ tests/OFUDPSocketTests.m @@ -17,11 +17,11 @@ #include #import "TestsAppDelegate.h" -static OFString *module = @"OFUDPSocket"; +static OFString *const module = @"OFUDPSocket"; @implementation TestsAppDelegate (OFUDPSocketTests) - (void)UDPSocketTests { void *pool = objc_autoreleasePoolPush(); Index: tests/OFURLTests.m ================================================================== --- tests/OFURLTests.m +++ tests/OFURLTests.m @@ -15,29 +15,29 @@ #include "config.h" #import "TestsAppDelegate.h" -static OFString *module = @"OFURL"; -static OFString *url_str = @"ht%3atp://us%3Aer:p%40w@ho%3Ast:1234/" +static OFString *const module = @"OFURL"; +static OFString *URLString = @"ht%3atp://us%3Aer:p%40w@ho%3Ast:1234/" @"pa%3Fth?que%23ry=1&f%26oo=b%3dar#frag%23ment"; @implementation TestsAppDelegate (OFURLTests) - (void)URLTests { void *pool = objc_autoreleasePoolPush(); - OFURL *u1, *u2, *u3, *u4, *u5, *u6, *u7; - OFMutableURL *mu; + OFURL *URL1, *URL2, *URL3, *URL4, *URL5, *URL6, *URL7; + OFMutableURL *mutableURL; TEST(@"+[URLWithString:]", - R(u1 = [OFURL URLWithString: url_str]) && - R(u2 = [OFURL URLWithString: @"http://foo:80"]) && - R(u3 = [OFURL URLWithString: @"http://bar/"]) && - R(u4 = [OFURL URLWithString: @"file:///etc/passwd"]) && - R(u5 = [OFURL URLWithString: @"http://foo/bar/qux/foo%2fbar"]) && - R(u6 = [OFURL URLWithString: @"https://[12:34::56:abcd]/"]) && - R(u7 = [OFURL URLWithString: @"https://[12:34::56:abcd]:234/"])) + R(URL1 = [OFURL URLWithString: URLString]) && + R(URL2 = [OFURL URLWithString: @"http://foo:80"]) && + R(URL3 = [OFURL URLWithString: @"http://bar/"]) && + R(URL4 = [OFURL URLWithString: @"file:///etc/passwd"]) && + R(URL5 = [OFURL URLWithString: @"http://foo/bar/qux/foo%2fbar"]) && + R(URL6 = [OFURL URLWithString: @"https://[12:34::56:abcd]/"]) && + R(URL7 = [OFURL URLWithString: @"https://[12:34::56:abcd]:234/"])) EXPECT_EXCEPTION(@"+[URLWithString:] fails with invalid characters #1", OFInvalidFormatException, [OFURL URLWithString: @"ht,tp://foo"]) @@ -68,20 +68,20 @@ EXPECT_EXCEPTION(@"+[URLWithString:] fails with invalid characters #8", OFInvalidFormatException, [OFURL URLWithString: @"https://[f]:f/"]) TEST(@"+[URLWithString:relativeToURL:]", - [[[OFURL URLWithString: @"/foo" relativeToURL: u1] string] isEqual: - @"ht%3atp://us%3Aer:p%40w@ho%3Ast:1234/foo"] && + [[[OFURL URLWithString: @"/foo" relativeToURL: URL1] string] + isEqual: @"ht%3atp://us%3Aer:p%40w@ho%3Ast:1234/foo"] && [[[OFURL URLWithString: @"foo/bar?q" relativeToURL: [OFURL URLWithString: @"http://h/qux/quux"]] string] isEqual: @"http://h/qux/foo/bar?q"] && [[[OFURL URLWithString: @"foo/bar" relativeToURL: [OFURL URLWithString: @"http://h/qux/?x"]] string] isEqual: @"http://h/qux/foo/bar"] && [[[OFURL URLWithString: @"http://foo/?q" - relativeToURL: u1] string] isEqual: @"http://foo/?q"] && + relativeToURL: URL1] string] isEqual: @"http://foo/?q"] && [[[OFURL URLWithString: @"foo" relativeToURL: [OFURL URLWithString: @"http://foo/bar"]] string] isEqual: @"http://foo/foo"] && [[[OFURL URLWithString: @"foo" relativeToURL: [OFURL URLWithString: @"http://foo"]] @@ -88,26 +88,26 @@ string] isEqual: @"http://foo/foo"]) EXPECT_EXCEPTION( @"+[URLWithString:relativeToURL:] fails with invalid characters #1", OFInvalidFormatException, - [OFURL URLWithString: @"`" relativeToURL: u1]) + [OFURL URLWithString: @"`" relativeToURL: URL1]) EXPECT_EXCEPTION( @"+[URLWithString:relativeToURL:] fails with invalid characters #2", OFInvalidFormatException, - [OFURL URLWithString: @"/`" relativeToURL: u1]) + [OFURL URLWithString: @"/`" relativeToURL: URL1]) EXPECT_EXCEPTION( @"+[URLWithString:relativeToURL:] fails with invalid characters #3", OFInvalidFormatException, - [OFURL URLWithString: @"?`" relativeToURL: u1]) + [OFURL URLWithString: @"?`" relativeToURL: URL1]) EXPECT_EXCEPTION( @"+[URLWithString:relativeToURL:] fails with invalid characters #4", OFInvalidFormatException, - [OFURL URLWithString: @"#`" relativeToURL: u1]) + [OFURL URLWithString: @"#`" relativeToURL: URL1]) #ifdef OF_HAVE_FILES TEST(@"+[fileURLWithPath:]", [[[OFURL fileURLWithPath: @"testfile.txt"] fileSystemRepresentation] isEqual: [[OFFileManager defaultManager].currentDirectoryPath @@ -133,34 +133,35 @@ [tmp.fileSystemRepresentation isEqual: @"\\\\test"]) # endif #endif TEST(@"-[string]", - [u1.string isEqual: url_str] && - [u2.string isEqual: @"http://foo:80"] && - [u3.string isEqual: @"http://bar/"] && - [u4.string isEqual: @"file:///etc/passwd"]) + [URL1.string isEqual: URLString] && + [URL2.string isEqual: @"http://foo:80"] && + [URL3.string isEqual: @"http://bar/"] && + [URL4.string isEqual: @"file:///etc/passwd"]) TEST(@"-[scheme]", - [u1.scheme isEqual: @"ht:tp"] && [u4.scheme isEqual: @"file"]) + [URL1.scheme isEqual: @"ht:tp"] && [URL4.scheme isEqual: @"file"]) - TEST(@"-[user]", [u1.user isEqual: @"us:er"] && u4.user == nil) + TEST(@"-[user]", [URL1.user isEqual: @"us:er"] && URL4.user == nil) TEST(@"-[password]", - [u1.password isEqual: @"p@w"] && u4.password == nil) - TEST(@"-[host]", [u1.host isEqual: @"ho:st"] && - [u6.host isEqual: @"12:34::56:abcd"] && - [u7.host isEqual: @"12:34::56:abcd"]) - TEST(@"-[port]", u1.port.unsignedShortValue == 1234 && - [u4 port] == nil && u7.port.unsignedShortValue == 234) + [URL1.password isEqual: @"p@w"] && URL4.password == nil) + TEST(@"-[host]", [URL1.host isEqual: @"ho:st"] && + [URL6.host isEqual: @"12:34::56:abcd"] && + [URL7.host isEqual: @"12:34::56:abcd"]) + TEST(@"-[port]", URL1.port.unsignedShortValue == 1234 && + [URL4 port] == nil && URL7.port.unsignedShortValue == 234) TEST(@"-[path]", - [u1.path isEqual: @"/pa?th"] && [u4.path isEqual: @"/etc/passwd"]) + [URL1.path isEqual: @"/pa?th"] && + [URL4.path isEqual: @"/etc/passwd"]) TEST(@"-[pathComponents]", - [u1.pathComponents isEqual: + [URL1.pathComponents isEqual: [OFArray arrayWithObjects: @"/", @"pa?th", nil]] && - [u4.pathComponents isEqual: + [URL4.pathComponents isEqual: [OFArray arrayWithObjects: @"/", @"etc", @"passwd", nil]] && - [u5.pathComponents isEqual: + [URL5.pathComponents isEqual: [OFArray arrayWithObjects: @"/", @"bar", @"qux", @"foo/bar", nil]]) TEST(@"-[lastPathComponent]", [[[OFURL URLWithString: @"http://host/foo//bar/baz"] lastPathComponent] isEqual: @"baz"] && [[[OFURL URLWithString: @"http://host/foo//bar/baz/"] @@ -167,124 +168,137 @@ lastPathComponent] isEqual: @"baz"] && [[[OFURL URLWithString: @"http://host/foo/"] lastPathComponent] isEqual: @"foo"] && [[[OFURL URLWithString: @"http://host/"] lastPathComponent] isEqual: @"/"] && - [u5.lastPathComponent isEqual: @"foo/bar"]) + [URL5.lastPathComponent isEqual: @"foo/bar"]) TEST(@"-[query]", - [u1.query isEqual: @"que#ry=1&f&oo=b=ar"] && u4.query == nil) + [URL1.query isEqual: @"que#ry=1&f&oo=b=ar"] && URL4.query == nil) TEST(@"-[queryDictionary]", - [u1.queryDictionary isEqual: + [URL1.queryDictionary isEqual: [OFDictionary dictionaryWithKeysAndObjects: @"que#ry", @"1", @"f&oo", @"b=ar", nil]]); TEST(@"-[fragment]", - [u1.fragment isEqual: @"frag#ment"] && u4.fragment == nil) - - TEST(@"-[copy]", R(u4 = [[u1 copy] autorelease])) - - TEST(@"-[isEqual:]", [u1 isEqual: u4] && ![u2 isEqual: u3] && - [[OFURL URLWithString: @"HTTP://bar/"] isEqual: u3]) - - TEST(@"-[hash:]", u1.hash == u4.hash && u2.hash != u3.hash) + [URL1.fragment isEqual: @"frag#ment"] && URL4.fragment == nil) + + TEST(@"-[copy]", R(URL4 = [[URL1 copy] autorelease])) + + TEST(@"-[isEqual:]", [URL1 isEqual: URL4] && ![URL2 isEqual: URL3] && + [[OFURL URLWithString: @"HTTP://bar/"] isEqual: URL3]) + + TEST(@"-[hash:]", URL1.hash == URL4.hash && URL2.hash != URL3.hash) EXPECT_EXCEPTION(@"Detection of invalid format", OFInvalidFormatException, [OFURL URLWithString: @"http"]) - mu = [OFMutableURL URL]; + mutableURL = [OFMutableURL URL]; TEST(@"-[setScheme:]", - (mu.scheme = @"ht:tp") && [mu.URLEncodedScheme isEqual: @"ht%3Atp"]) + (mutableURL.scheme = @"ht:tp") && + [mutableURL.URLEncodedScheme isEqual: @"ht%3Atp"]) TEST(@"-[setURLEncodedScheme:]", - (mu.URLEncodedScheme = @"ht%3Atp") && [mu.scheme isEqual: @"ht:tp"]) + (mutableURL.URLEncodedScheme = @"ht%3Atp") && + [mutableURL.scheme isEqual: @"ht:tp"]) EXPECT_EXCEPTION( @"-[setURLEncodedScheme:] with invalid characters fails", - OFInvalidFormatException, mu.URLEncodedScheme = @"~") - - TEST(@"-[setHost:]", - (mu.host = @"ho:st") && [mu.URLEncodedHost isEqual: @"ho%3Ast"] && - (mu.host = @"12:34:ab") && - [mu.URLEncodedHost isEqual: @"[12:34:ab]"] && - (mu.host = @"12:34:aB") && - [mu.URLEncodedHost isEqual: @"[12:34:aB]"] && - (mu.host = @"12:34:g") && - [mu.URLEncodedHost isEqual: @"12%3A34%3Ag"]) - - TEST(@"-[setURLEncodedHost:]", - (mu.URLEncodedHost = @"ho%3Ast") && [mu.host isEqual: @"ho:st"] && - (mu.URLEncodedHost = @"[12:34]") && [mu.host isEqual: @"12:34"] && - (mu.URLEncodedHost = @"[12::ab]") && [mu.host isEqual: @"12::ab"]) - - EXPECT_EXCEPTION(@"-[setURLEncodedHost:] with invalid characters fails" - " #1", OFInvalidFormatException, mu.URLEncodedHost = @"/") - - EXPECT_EXCEPTION(@"-[setURLEncodedHost:] with invalid characters fails" - " #2", OFInvalidFormatException, mu.URLEncodedHost = @"[12:34") - - EXPECT_EXCEPTION(@"-[setURLEncodedHost:] with invalid characters fails" - " #3", OFInvalidFormatException, mu.URLEncodedHost = @"[a::g]") - - TEST(@"-[setUser:]", - (mu.user = @"us:er") && [mu.URLEncodedUser isEqual: @"us%3Aer"]) - - TEST(@"-[setURLEncodedUser:]", - (mu.URLEncodedUser = @"us%3Aer") && [mu.user isEqual: @"us:er"]) - - EXPECT_EXCEPTION(@"-[setURLEncodedUser:] with invalid characters fails", - OFInvalidFormatException, mu.URLEncodedHost = @"/") - - TEST(@"-[setPassword:]", - (mu.password = @"pass:word") && - [mu.URLEncodedPassword isEqual: @"pass%3Aword"]) - - TEST(@"-[setURLEncodedPassword:]", - (mu.URLEncodedPassword = @"pass%3Aword") && - [mu.password isEqual: @"pass:word"]) + OFInvalidFormatException, mutableURL.URLEncodedScheme = @"~") + + TEST(@"-[setHost:]", + (mutableURL.host = @"ho:st") && + [mutableURL.URLEncodedHost isEqual: @"ho%3Ast"] && + (mutableURL.host = @"12:34:ab") && + [mutableURL.URLEncodedHost isEqual: @"[12:34:ab]"] && + (mutableURL.host = @"12:34:aB") && + [mutableURL.URLEncodedHost isEqual: @"[12:34:aB]"] && + (mutableURL.host = @"12:34:g") && + [mutableURL.URLEncodedHost isEqual: @"12%3A34%3Ag"]) + + TEST(@"-[setURLEncodedHost:]", + (mutableURL.URLEncodedHost = @"ho%3Ast") && + [mutableURL.host isEqual: @"ho:st"] && + (mutableURL.URLEncodedHost = @"[12:34]") && + [mutableURL.host isEqual: @"12:34"] && + (mutableURL.URLEncodedHost = @"[12::ab]") && + [mutableURL.host isEqual: @"12::ab"]) + + EXPECT_EXCEPTION(@"-[setURLEncodedHost:] with invalid characters fails" + " #1", OFInvalidFormatException, mutableURL.URLEncodedHost = @"/") + + EXPECT_EXCEPTION(@"-[setURLEncodedHost:] with invalid characters fails" + " #2", OFInvalidFormatException, + mutableURL.URLEncodedHost = @"[12:34") + + EXPECT_EXCEPTION(@"-[setURLEncodedHost:] with invalid characters fails" + " #3", OFInvalidFormatException, + mutableURL.URLEncodedHost = @"[a::g]") + + TEST(@"-[setUser:]", + (mutableURL.user = @"us:er") && + [mutableURL.URLEncodedUser isEqual: @"us%3Aer"]) + + TEST(@"-[setURLEncodedUser:]", + (mutableURL.URLEncodedUser = @"us%3Aer") && + [mutableURL.user isEqual: @"us:er"]) + + EXPECT_EXCEPTION(@"-[setURLEncodedUser:] with invalid characters fails", + OFInvalidFormatException, mutableURL.URLEncodedHost = @"/") + + TEST(@"-[setPassword:]", + (mutableURL.password = @"pass:word") && + [mutableURL.URLEncodedPassword isEqual: @"pass%3Aword"]) + + TEST(@"-[setURLEncodedPassword:]", + (mutableURL.URLEncodedPassword = @"pass%3Aword") && + [mutableURL.password isEqual: @"pass:word"]) EXPECT_EXCEPTION( @"-[setURLEncodedPassword:] with invalid characters fails", - OFInvalidFormatException, mu.URLEncodedPassword = @"/") + OFInvalidFormatException, mutableURL.URLEncodedPassword = @"/") TEST(@"-[setPath:]", - (mu.path = @"pa/th@?") && [mu.URLEncodedPath isEqual: @"pa/th@%3F"]) + (mutableURL.path = @"pa/th@?") && + [mutableURL.URLEncodedPath isEqual: @"pa/th@%3F"]) TEST(@"-[setURLEncodedPath:]", - (mu.URLEncodedPath = @"pa/th@%3F") && [mu.path isEqual: @"pa/th@?"]) + (mutableURL.URLEncodedPath = @"pa/th@%3F") && + [mutableURL.path isEqual: @"pa/th@?"]) EXPECT_EXCEPTION(@"-[setURLEncodedPath:] with invalid characters fails", - OFInvalidFormatException, mu.URLEncodedPath = @"?") + OFInvalidFormatException, mutableURL.URLEncodedPath = @"?") TEST(@"-[setQuery:]", - (mu.query = @"que/ry?#") && - [mu.URLEncodedQuery isEqual: @"que/ry?%23"]) + (mutableURL.query = @"que/ry?#") && + [mutableURL.URLEncodedQuery isEqual: @"que/ry?%23"]) TEST(@"-[setURLEncodedQuery:]", - (mu.URLEncodedQuery = @"que/ry?%23") && - [mu.query isEqual: @"que/ry?#"]) + (mutableURL.URLEncodedQuery = @"que/ry?%23") && + [mutableURL.query isEqual: @"que/ry?#"]) EXPECT_EXCEPTION( @"-[setURLEncodedQuery:] with invalid characters fails", - OFInvalidFormatException, mu.URLEncodedQuery = @"`") + OFInvalidFormatException, mutableURL.URLEncodedQuery = @"`") TEST(@"-[setQueryDictionary:]", - (mu.queryDictionary = [OFDictionary dictionaryWithKeysAndObjects: + (mutableURL.queryDictionary = + [OFDictionary dictionaryWithKeysAndObjects: @"foo&bar", @"baz=qux", @"f=oobar", @"b&azqux", nil]) && - [mu.URLEncodedQuery isEqual: + [mutableURL.URLEncodedQuery isEqual: @"foo%26bar=baz%3Dqux&f%3Doobar=b%26azqux"]) TEST(@"-[setFragment:]", - (mu.fragment = @"frag/ment?#") && - [mu.URLEncodedFragment isEqual: @"frag/ment?%23"]) + (mutableURL.fragment = @"frag/ment?#") && + [mutableURL.URLEncodedFragment isEqual: @"frag/ment?%23"]) TEST(@"-[setURLEncodedFragment:]", - (mu.URLEncodedFragment = @"frag/ment?%23") && - [mu.fragment isEqual: @"frag/ment?#"]) + (mutableURL.URLEncodedFragment = @"frag/ment?%23") && + [mutableURL.fragment isEqual: @"frag/ment?#"]) EXPECT_EXCEPTION( @"-[setURLEncodedFragment:] with invalid characters fails", - OFInvalidFormatException, mu.URLEncodedFragment = @"`") + OFInvalidFormatException, mutableURL.URLEncodedFragment = @"`") TEST(@"-[URLByAppendingPathComponent:isDirectory:]", [[[OFURL URLWithString: @"file:///foo/bar"] URLByAppendingPathComponent: @"qux" isDirectory: false] isEqual: [OFURL URLWithString: @"file:///foo/bar/qux"]] && Index: tests/OFValueTests.m ================================================================== --- tests/OFValueTests.m +++ tests/OFValueTests.m @@ -17,11 +17,11 @@ #include #import "TestsAppDelegate.h" -static OFString *module = @"OFValue"; +static OFString *const module = @"OFValue"; @implementation TestsAppDelegate (OFValueTests) - (void)valueTests { void *pool = objc_autoreleasePoolPush(); Index: tests/OFWindowsRegistryKeyTests.m ================================================================== --- tests/OFWindowsRegistryKeyTests.m +++ tests/OFWindowsRegistryKeyTests.m @@ -15,18 +15,18 @@ #include "config.h" #import "TestsAppDelegate.h" -static OFString *module = @"OFWindowsRegistryKey"; +static OFString *const module = @"OFWindowsRegistryKey"; @implementation TestsAppDelegate (OFWindowsRegistryKeyTests) - (void)windowsRegistryKeyTests { void *pool = objc_autoreleasePoolPush(); OFData *data = [OFData dataWithItems: "abcdef" count: 6]; - OFWindowsRegistryKey *softwareKey, *ObjFWKey; + OFWindowsRegistryKey *softwareKey, *objFWKey; DWORD type; TEST(@"+[OFWindowsRegistryKey classesRootKey]", [OFWindowsRegistryKey classesRootKey]) @@ -49,35 +49,35 @@ [[OFWindowsRegistryKey currentUserKey] openSubkeyAtPath: @"nonexistent" securityAndAccessRights: KEY_ALL_ACCESS] == nil) TEST(@"-[createSubkeyAtPath:securityAndAccessRights:]", - (ObjFWKey = [softwareKey createSubkeyAtPath: @"ObjFW" + (objFWKey = [softwareKey createSubkeyAtPath: @"ObjFW" securityAndAccessRights: KEY_ALL_ACCESS])) TEST(@"-[setData:forValueNamed:type:]", - R([ObjFWKey setData: data forValueNamed: @"data" type: REG_BINARY])) + R([objFWKey setData: data forValueNamed: @"data" type: REG_BINARY])) TEST(@"-[dataForValueNamed:subkeyPath:flags:type:]", - [[ObjFWKey dataForValueNamed: @"data" type: &type] isEqual: data] && + [[objFWKey dataForValueNamed: @"data" type: &type] isEqual: data] && type == REG_BINARY) TEST(@"-[setString:forValueNamed:type:]", - R([ObjFWKey setString: @"foobar" forValueNamed: @"string"]) && - R([ObjFWKey setString: @"%PATH%;foo" + R([objFWKey setString: @"foobar" forValueNamed: @"string"]) && + R([objFWKey setString: @"%PATH%;foo" forValueNamed: @"expand" type: REG_EXPAND_SZ])) TEST(@"-[stringForValue:subkeyPath:]", - [[ObjFWKey stringForValueNamed: @"string"] isEqual: @"foobar"] && - [[ObjFWKey stringForValueNamed: @"expand" type: &type] + [[objFWKey stringForValueNamed: @"string"] isEqual: @"foobar"] && + [[objFWKey stringForValueNamed: @"expand" type: &type] isEqual: @"%PATH%;foo"] && type == REG_EXPAND_SZ) - TEST(@"-[deleteValueNamed:]", R([ObjFWKey deleteValueNamed: @"data"])) + TEST(@"-[deleteValueNamed:]", R([objFWKey deleteValueNamed: @"data"])) TEST(@"-[deleteSubkeyAtPath:]", R([softwareKey deleteSubkeyAtPath: @"ObjFW"])) objc_autoreleasePoolPop(pool); } @end Index: tests/OFXMLElementBuilderTests.m ================================================================== --- tests/OFXMLElementBuilderTests.m +++ tests/OFXMLElementBuilderTests.m @@ -15,11 +15,11 @@ #include "config.h" #import "TestsAppDelegate.h" -static OFString *module = @"OFXMLElementBuilder"; +static OFString *const module = @"OFXMLElementBuilder"; static OFXMLNode *nodes[2]; static size_t i = 0; @implementation TestsAppDelegate (OFXMLElementBuilderTests) - (void)elementBuilder: (OFXMLElementBuilder *)builder @@ -37,26 +37,26 @@ } - (void)XMLElementBuilderTests { void *pool = objc_autoreleasePoolPush(); - OFXMLParser *p = [OFXMLParser parser]; + OFXMLParser *parser = [OFXMLParser parser]; OFXMLElementBuilder *builder = [OFXMLElementBuilder builder]; - OFString *str = @"barbaz" + OFString *string = @"barbaz" " " ""; - p.delegate = builder; + parser.delegate = builder; builder.delegate = self; TEST(@"Building elements from parsed XML", - R([p parseString: str]) && - nodes[0] != nil && [nodes[0].XMLString isEqual: str] && - R([p parseString: @""]) && + R([parser parseString: string]) && + nodes[0] != nil && [nodes[0].XMLString isEqual: string] && + R([parser parseString: @""]) && nodes[1] != nil && [nodes[1].XMLString isEqual: @""] && i == 2) [nodes[0] release]; [nodes[1] release]; objc_autoreleasePoolPop(pool); } @end Index: tests/OFXMLNodeTests.m ================================================================== --- tests/OFXMLNodeTests.m +++ tests/OFXMLNodeTests.m @@ -15,112 +15,112 @@ #include "config.h" #import "TestsAppDelegate.h" -static OFString *module = @"OFXMLNode"; +static OFString *module; @implementation TestsAppDelegate (OFXMLNodeTests) - (void)XMLNodeTests { void *pool = objc_autoreleasePoolPush(); - id nodes[4]; - OFArray *a; + id node1, node2, node3, node4; + OFArray *array; + + module = @"OFXMLNode"; TEST(@"+[elementWithName:]", - (nodes[0] = [OFXMLElement elementWithName: @"foo"]) && - [[nodes[0] XMLString] isEqual: @""]) + (node1 = [OFXMLElement elementWithName: @"foo"]) && + [[node1 XMLString] isEqual: @""]) TEST(@"+[elementWithName:stringValue:]", - (nodes[1] = [OFXMLElement elementWithName: @"foo" - stringValue: @"b&ar"]) && - [[nodes[1] XMLString] isEqual: @"b&ar"]) + (node2 = [OFXMLElement elementWithName: @"foo" + stringValue: @"b&ar"]) && + [[node2 XMLString] isEqual: @"b&ar"]) TEST(@"+[elementWithName:namespace:]", - (nodes[2] = [OFXMLElement elementWithName: @"foo" - namespace: @"urn:objfw:test"]) && - R([nodes[2] addAttributeWithName: @"test" stringValue: @"test"]) && - R([nodes[2] setPrefix: @"objfw-test" - forNamespace: @"urn:objfw:test"]) && - [[nodes[2] XMLString] isEqual: @""] && - (nodes[3] = [OFXMLElement elementWithName: @"foo" - namespace: @"urn:objfw:test"]) && - R([nodes[3] addAttributeWithName: @"test" stringValue: @"test"]) && - [[nodes[3] XMLString] isEqual: + (node3 = [OFXMLElement elementWithName: @"foo" + namespace: @"urn:objfw:test"]) && + R([node3 addAttributeWithName: @"test" stringValue: @"test"]) && + R([node3 setPrefix: @"objfw-test" + forNamespace: @"urn:objfw:test"]) && + [[node3 XMLString] isEqual: @""] && + (node4 = [OFXMLElement elementWithName: @"foo" + namespace: @"urn:objfw:test"]) && + R([node4 addAttributeWithName: @"test" stringValue: @"test"]) && + [[node4 XMLString] isEqual: @""]) TEST(@"+[elementWithName:namespace:stringValue:]", - (nodes[3] = [OFXMLElement elementWithName: @"foo" - namespace: @"urn:objfw:test" - stringValue: @"x"]) && - R([nodes[3] setPrefix: @"objfw-test" - forNamespace: @"urn:objfw:test"]) && - [[nodes[3] XMLString] isEqual: - @"x"]) + (node4 = [OFXMLElement elementWithName: @"foo" + namespace: @"urn:objfw:test" + stringValue: @"x"]) && + R([node4 setPrefix: @"objfw-test" + forNamespace: @"urn:objfw:test"]) && + [[node4 XMLString] isEqual: @"x"]) TEST(@"+[charactersWithString:]", - (nodes[3] = [OFXMLCharacters charactersWithString: @""]) && - [[nodes[3] XMLString] isEqual: @"<foo>"]) + (node4 = [OFXMLCharacters charactersWithString: @""]) && + [[node4 XMLString] isEqual: @"<foo>"]) TEST(@"+[CDATAWithString:]", - (nodes[3] = [OFXMLCDATA CDATAWithString: @""]) && - [[nodes[3] XMLString] isEqual: @"]]>"]); + (node4 = [OFXMLCDATA CDATAWithString: @""]) && + [[node4 XMLString] isEqual: @"]]>"]); TEST(@"+[commentWithText:]", - (nodes[3] = [OFXMLComment commentWithText: @" comment "]) && - [[nodes[3] XMLString] isEqual: @""]) + (node4 = [OFXMLComment commentWithText: @" comment "]) && + [[node4 XMLString] isEqual: @""]) module = @"OFXMLElement"; TEST(@"-[addAttributeWithName:stringValue:]", - R([nodes[0] addAttributeWithName: @"foo" stringValue: @"b&ar"]) && - [[nodes[0] XMLString] isEqual: @""] && - R([nodes[1] addAttributeWithName: @"foo" stringValue: @"b&ar"]) && - [[nodes[1] XMLString] isEqual: - @"b&ar"]) + R([node1 addAttributeWithName: @"foo" stringValue: @"b&ar"]) && + [[node1 XMLString] isEqual: @""] && + R([node2 addAttributeWithName: @"foo" stringValue: @"b&ar"]) && + [[node2 XMLString] isEqual: @"b&ar"]) TEST(@"-[setPrefix:forNamespace:]", - R([nodes[1] setPrefix: @"objfw-test" - forNamespace: @"urn:objfw:test"])) + R([node2 setPrefix: @"objfw-test" + forNamespace: @"urn:objfw:test"])) TEST(@"-[addAttributeWithName:namespace:stringValue:]", - R([nodes[1] addAttributeWithName: @"foo" - namespace: @"urn:objfw:test" - stringValue: @"bar"]) && - R([nodes[1] addAttributeWithName: @"foo" - namespace: @"urn:objfw:test" - stringValue: @"ignored"]) && - [[nodes[1] XMLString] isEqual: + R([node2 addAttributeWithName: @"foo" + namespace: @"urn:objfw:test" + stringValue: @"bar"]) && + R([node2 addAttributeWithName: @"foo" + namespace: @"urn:objfw:test" + stringValue: @"ignored"]) && + [[node2 XMLString] isEqual: @"b&ar"]) TEST(@"-[removeAttributeForName:namespace:]", - R([nodes[1] removeAttributeForName: @"foo"]) && - [[nodes[1] XMLString] isEqual: + R([node2 removeAttributeForName: @"foo"]) && + [[node2 XMLString] isEqual: @"b&ar"] && - R([nodes[1] removeAttributeForName: @"foo" - namespace: @"urn:objfw:test"]) && - [[nodes[1] XMLString] isEqual: @"b&ar"]) + R([node2 removeAttributeForName: @"foo" + namespace: @"urn:objfw:test"]) && + [[node2 XMLString] isEqual: @"b&ar"]) TEST(@"-[addChild:]", - R([nodes[0] addChild: [OFXMLElement elementWithName: @"bar"]]) && - [[nodes[0] XMLString] isEqual: + R([node1 addChild: [OFXMLElement elementWithName: @"bar"]]) && + [[node1 XMLString] isEqual: @""] && - R([nodes[2] addChild: [OFXMLElement elementWithName: @"bar" - namespace: @"urn:objfw:test"]]) && - [[nodes[2] XMLString] isEqual: + R([node3 addChild: [OFXMLElement elementWithName: @"bar" + namespace: @"urn:objfw:test"]]) && + [[node3 XMLString] isEqual: @""]) TEST(@"+[elementWithXMLString:] and -[stringValue]", [[[OFXMLElement elementWithXMLString: @"\r\nfoo" @"bazqux"] stringValue] isEqual: @"foobarbazqux"]) TEST(@"-[elementsForName:namespace:]", - (a = [nodes[2] elementsForName: @"bar" - namespace: @"urn:objfw:test"]) && - a.count == 1 && [[[a firstObject] XMLString] isEqual: + (array = [node3 elementsForName: @"bar" + namespace: @"urn:objfw:test"]) && + array.count == 1 && [[array.firstObject XMLString] isEqual: @""]) TEST(@"-[isEqual:]", [[OFXMLElement elementWithXMLString: @""] isEqual: [OFXMLElement elementWithXMLString: @""]] && Index: tests/OFXMLParserTests.m ================================================================== --- tests/OFXMLParserTests.m +++ tests/OFXMLParserTests.m @@ -18,99 +18,114 @@ #include #include #import "TestsAppDelegate.h" -static OFString *module = @"OFXMLParser"; +static OFString *const module = @"OFXMLParser"; static int i = 0; -enum event_type { - PROCESSING_INSTRUCTION, - TAG_OPEN, - TAG_CLOSE, - STRING, - CDATA, - COMMENT +enum EventType { + eventTypeProcessingInstruction, + eventTypeTagOpen, + eventTypeTagClose, + eventTypeString, + eventTypeCDATA, + eventTypeComment }; @implementation TestsAppDelegate (OFXMLParser) - (void)parser: (OFXMLParser *)parser - didCreateEvent: (enum event_type)type + didCreateEvent: (enum EventType)type name: (OFString *)name prefix: (OFString *)prefix - namespace: (OFString *)ns + namespace: (OFString *)namespace attributes: (OFArray *)attrs string: (OFString *)string { - OFString *msg; + OFString *message; i++; - msg = [OFString stringWithFormat: @"Parsing part #%d", i]; + message = [OFString stringWithFormat: @"Parsing part #%d", i]; switch (i) { case 1: - TEST(msg, type == PROCESSING_INSTRUCTION && + TEST(message, + type == eventTypeProcessingInstruction && [name isEqual: @"xml"] && [string isEqual: @"version='1.0'"]) break; case 2: - TEST(msg, type == PROCESSING_INSTRUCTION && + TEST(message, + type == eventTypeProcessingInstruction && [name isEqual: @"p?i"] && string == nil) break; case 3: - TEST(msg, type == TAG_OPEN && [name isEqual: @"root"] && - prefix == nil && ns == nil && attrs.count == 0) + TEST(message, + type == eventTypeTagOpen && [name isEqual: @"root"] && + prefix == nil && namespace == nil && attrs.count == 0) break; case 4: - TEST(msg, type == STRING && [string isEqual: @"\n\n "]) + TEST(message, + type == eventTypeString && [string isEqual: @"\n\n "]) break; case 5: - TEST(msg, type == CDATA && [string isEqual: @"f<]]]oo]"] && + TEST(message, + type == eventTypeCDATA && [string isEqual: @"f<]]]oo]"] && parser.lineNumber == 3) break; case 6: - TEST(msg, type == TAG_OPEN && [name isEqual: @"bar"] && - prefix == nil && ns == nil && attrs == nil) + TEST(message, + type == eventTypeTagOpen && [name isEqual: @"bar"] && + prefix == nil && namespace == nil && attrs == nil) break; case 7: - TEST(msg, type == TAG_CLOSE && [name isEqual: @"bar"] && - prefix == nil && ns == nil && attrs == nil) + TEST(message, + type == eventTypeTagClose && [name isEqual: @"bar"] && + prefix == nil && namespace == nil && attrs == nil) break; case 8: - TEST(msg, type == STRING && [string isEqual: @"\n "]) + TEST(message, + type == eventTypeString && [string isEqual: @"\n "]) break; case 9: - TEST(msg, type == TAG_OPEN && [name isEqual: @"foobar"] && - prefix == nil && [ns isEqual: @"urn:objfw:test:foobar"] && + TEST(message, + type == eventTypeTagOpen && [name isEqual: @"foobar"] && + prefix == nil && + [namespace isEqual: @"urn:objfw:test:foobar"] && attrs.count == 1 && /* xmlns attr */ [[[attrs objectAtIndex: 0] name] isEqual: @"xmlns"] && [[attrs objectAtIndex: 0] namespace] == nil && [[[attrs objectAtIndex: 0] stringValue] isEqual: @"urn:objfw:test:foobar"]) break; case 10: - TEST(msg, type == STRING && [string isEqual: @"\n "]) + TEST(message, + type == eventTypeString && [string isEqual: @"\n "]) break; case 11: - TEST(msg, type == TAG_OPEN && [name isEqual: @"qux"] && - prefix == nil && [ns isEqual: @"urn:objfw:test:foobar"] && + TEST(message, + type == eventTypeTagOpen && [name isEqual: @"qux"] && + prefix == nil && + [namespace isEqual: @"urn:objfw:test:foobar"] && attrs.count == 1 && /* xmlns:foo attr */ [[[attrs objectAtIndex: 0] name] isEqual: @"foo"] && [[[attrs objectAtIndex: 0] namespace] isEqual: @"http://www.w3.org/2000/xmlns/"] && [[[attrs objectAtIndex: 0] stringValue] isEqual: @"urn:objfw:test:foo"]) break; case 12: - TEST(msg, type == STRING && [string isEqual: @"\n "]) + TEST(message, + type == eventTypeString && [string isEqual: @"\n "]) break; case 13: - TEST(msg, type == TAG_OPEN && [name isEqual: @"bla"] && + TEST(message, + type == eventTypeTagOpen && [name isEqual: @"bla"] && [prefix isEqual: @"foo"] && - [ns isEqual: @"urn:objfw:test:foo"] && + [namespace isEqual: @"urn:objfw:test:foo"] && attrs.count == 2 && /* foo:bla attr */ [[[attrs objectAtIndex: 0] name] isEqual: @"bla"] && [[[attrs objectAtIndex: 0] namespace] isEqual: @"urn:objfw:test:foo"] && @@ -119,15 +134,18 @@ [[[attrs objectAtIndex: 1] name] isEqual: @"blafoo"] && [[attrs objectAtIndex: 1] namespace] == nil && [[[attrs objectAtIndex: 1] stringValue] isEqual: @"foo"]) break; case 14: - TEST(msg, type == STRING && [string isEqual: @"\n "]) + TEST(message, + type == eventTypeString && [string isEqual: @"\n "]) break; case 15: - TEST(msg, type == TAG_OPEN && [name isEqual: @"blup"] && - prefix == nil && [ns isEqual: @"urn:objfw:test:foobar"] && + TEST(message, + type == eventTypeTagOpen && [name isEqual: @"blup"] && + prefix == nil && + [namespace isEqual: @"urn:objfw:test:foobar"] && attrs.count == 2 && /* foo:qux attr */ [[[attrs objectAtIndex: 0] name] isEqual: @"qux"] && [[[attrs objectAtIndex: 0] namespace] isEqual: @"urn:objfw:test:foo"] && @@ -136,20 +154,25 @@ [[[attrs objectAtIndex: 1] name] isEqual: @"quxqux"] && [[attrs objectAtIndex: 1] namespace] == nil && [[[attrs objectAtIndex: 1] stringValue] isEqual: @"test"]) break; case 16: - TEST(msg, type == TAG_CLOSE && [name isEqual: @"blup"] && - prefix == nil && [ns isEqual: @"urn:objfw:test:foobar"]) + TEST(message, + type == eventTypeTagClose && [name isEqual: @"blup"] && + prefix == nil && + [namespace isEqual: @"urn:objfw:test:foobar"]) break; case 17: - TEST(msg, type == STRING && [string isEqual: @"\n "]) + TEST(message, + type == eventTypeString && [string isEqual: @"\n "]) break; case 18: - TEST(msg, type == TAG_OPEN && [name isEqual: @"bla"] && + TEST(message, + type == eventTypeTagOpen && [name isEqual: @"bla"] && [prefix isEqual: @"bla"] && - [ns isEqual: @"urn:objfw:test:bla"] && attrs.count == 3 && + [namespace isEqual: @"urn:objfw:test:bla"] && + attrs.count == 3 && /* xmlns:bla attr */ [[[attrs objectAtIndex: 0] name] isEqual: @"bla"] && [[[attrs objectAtIndex: 0] namespace] isEqual: @"http://www.w3.org/2000/xmlns/"] && [[[attrs objectAtIndex: 0] stringValue] isEqual: @@ -163,20 +186,24 @@ [[[attrs objectAtIndex: 2] namespace] isEqual: @"urn:objfw:test:bla"] && [[[attrs objectAtIndex: 2] stringValue] isEqual: @"blafoo"]) break; case 19: - TEST(msg, type == TAG_CLOSE && [name isEqual: @"bla"] && + TEST(message, + type == eventTypeTagClose && [name isEqual: @"bla"] && [prefix isEqual: @"bla"] && - [ns isEqual: @"urn:objfw:test:bla"]) + [namespace isEqual: @"urn:objfw:test:bla"]) break; case 20: - TEST(msg, type == STRING && [string isEqual: @"\n "]) + TEST(message, + type == eventTypeString && [string isEqual: @"\n "]) break; case 21: - TEST(msg, type == TAG_OPEN && [name isEqual: @"abc"] && - prefix == nil && [ns isEqual: @"urn:objfw:test:abc"] && + TEST(message, + type == eventTypeTagOpen && [name isEqual: @"abc"] && + prefix == nil && + [namespace isEqual: @"urn:objfw:test:abc"] && attrs.count == 3 && /* xmlns attr */ [[[attrs objectAtIndex: 0] name] isEqual: @"xmlns"] && [[attrs objectAtIndex: 0] namespace] == nil && [[[attrs objectAtIndex: 0] stringValue] isEqual: @@ -190,57 +217,70 @@ [[[attrs objectAtIndex: 2] namespace] isEqual: @"urn:objfw:test:foo"] && [[[attrs objectAtIndex: 2] stringValue] isEqual: @"abc"]) break; case 22: - TEST(msg, type == TAG_CLOSE && [name isEqual: @"abc"] && - prefix == nil && [ns isEqual: @"urn:objfw:test:abc"]) + TEST(message, + type == eventTypeTagClose && [name isEqual: @"abc"] && + prefix == nil && [namespace isEqual: @"urn:objfw:test:abc"]) break; case 23: - TEST(msg, type == STRING && [string isEqual: @"\n "]) + TEST(message, + type == eventTypeString && [string isEqual: @"\n "]) break; case 24: - TEST(msg, type == TAG_CLOSE && [name isEqual: @"bla"] && + TEST(message, + type == eventTypeTagClose && [name isEqual: @"bla"] && [prefix isEqual: @"foo"] && - [ns isEqual: @"urn:objfw:test:foo"]) + [namespace isEqual: @"urn:objfw:test:foo"]) break; case 25: - TEST(msg, type == STRING && [string isEqual: @"\n "]) + TEST(message, + type == eventTypeString && [string isEqual: @"\n "]) break; case 26: - TEST(msg, type == COMMENT && [string isEqual: @" commänt "]) + TEST(message, + type == eventTypeComment && [string isEqual: @" commänt "]) break; case 27: - TEST(msg, type == STRING && [string isEqual: @"\n "]) + TEST(message, + type == eventTypeString && [string isEqual: @"\n "]) break; case 28: - TEST(msg, type == TAG_CLOSE && [name isEqual: @"qux"] && - prefix == nil && [ns isEqual: @"urn:objfw:test:foobar"]) + TEST(message, + type == eventTypeTagClose && [name isEqual: @"qux"] && + prefix == nil && + [namespace isEqual: @"urn:objfw:test:foobar"]) break; case 29: - TEST(msg, type == STRING && [string isEqual: @"\n "]) + TEST(message, + type == eventTypeString && [string isEqual: @"\n "]) break; case 30: - TEST(msg, type == TAG_CLOSE && [name isEqual: @"foobar"] && - prefix == nil && [ns isEqual: @"urn:objfw:test:foobar"]) + TEST(message, + type == eventTypeTagClose && [name isEqual: @"foobar"] && + prefix == nil && + [namespace isEqual: @"urn:objfw:test:foobar"]) break; case 31: - TEST(msg, type == STRING && [string isEqual: @"\n"]) + TEST(message, + type == eventTypeString && [string isEqual: @"\n"]) break; case 32: - TEST(msg, type == TAG_CLOSE && [name isEqual: @"root"] && - prefix == nil && ns == nil); + TEST(message, + type == eventTypeTagClose && [name isEqual: @"root"] && + prefix == nil && namespace == nil); break; } } - (void)parser: (OFXMLParser *)parser foundProcessingInstructionWithTarget: (OFString *)target data: (OFString *)data { [self parser: parser - didCreateEvent: PROCESSING_INSTRUCTION + didCreateEvent: eventTypeProcessingInstruction name: target prefix: nil namespace: nil attributes: nil string: data]; @@ -247,62 +287,62 @@ } - (void)parser: (OFXMLParser *)parser didStartElement: (OFString *)name prefix: (OFString *)prefix - namespace: (OFString *)ns + namespace: (OFString *)namespace attributes: (OFArray *)attrs { [self parser: parser - didCreateEvent: TAG_OPEN + didCreateEvent: eventTypeTagOpen name: name prefix: prefix - namespace: ns + namespace: namespace attributes: attrs string: nil]; } - (void)parser: (OFXMLParser *)parser didEndElement: (OFString *)name prefix: (OFString *)prefix - namespace: (OFString *)ns + namespace: (OFString *)namespace { [self parser: parser - didCreateEvent: TAG_CLOSE + didCreateEvent: eventTypeTagClose name: name prefix: prefix - namespace: ns + namespace: namespace attributes: nil string: nil]; } - (void)parser: (OFXMLParser *)parser foundCharacters: (OFString *)string { [self parser: parser - didCreateEvent: STRING + didCreateEvent: eventTypeString name: nil prefix: nil namespace: nil attributes: nil string: string]; } -- (void)parser: (OFXMLParser *)parser foundCDATA: (OFString *)cdata +- (void)parser: (OFXMLParser *)parser foundCDATA: (OFString *)CDATA { [self parser: parser - didCreateEvent: CDATA + didCreateEvent: eventTypeCDATA name: nil prefix: nil namespace: nil attributes: nil - string: cdata]; + string: CDATA]; } - (void)parser: (OFXMLParser *)parser foundComment: (OFString *)comment { [self parser: parser - didCreateEvent: COMMENT + didCreateEvent: eventTypeComment name: nil prefix: nil namespace: nil attributes: nil string: comment]; @@ -318,11 +358,11 @@ } - (void)XMLParserTests { void *pool = objc_autoreleasePoolPush(); - const char *str = "\xEF\xBB\xBF" + const char *string = "\xEF\xBB\xBF" "\r\r" " \n" " \r\n" " \n" " \n" @@ -334,27 +374,27 @@ " \n" " \n" " \n" ""; OFXMLParser *parser; - size_t j, len; + size_t j, length; TEST(@"+[parser]", (parser = [OFXMLParser parser])) TEST(@"-[setDelegate:]", (parser.delegate = self)) /* Simulate a stream where we only get chunks */ - len = strlen(str); + length = strlen(string); - for (j = 0; j < len; j+= 2) { + for (j = 0; j < length; j+= 2) { if (parser.hasFinishedParsing) abort(); - if (j + 2 > len) - [parser parseBuffer: str + j length: 1]; + if (j + 2 > length) + [parser parseBuffer: string + j length: 1]; else - [parser parseBuffer: str + j length: 2]; + [parser parseBuffer: string + j length: 2]; } TEST(@"Checking if everything was parsed", i == 32 && parser.lineNumber == 18) DELETED tests/PBKDF2Tests.m Index: tests/PBKDF2Tests.m ================================================================== --- tests/PBKDF2Tests.m +++ tests/PBKDF2Tests.m @@ -1,125 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#include - -#import "TestsAppDelegate.h" - -static OFString *module = @"PBKDF2"; - -@implementation TestsAppDelegate (PBKDF2Tests) -- (void)PBKDF2Tests -{ - void *pool = objc_autoreleasePoolPush(); - OFHMAC *HMAC = [OFHMAC HMACWithHashClass: [OFSHA1Hash class] - allowsSwappableMemory: true]; - unsigned char key[25]; - - /* Test vectors from RFC 6070 */ - - TEST(@"PBKDF2-SHA1, 1 iteration", - R(OFPBKDF2((OFPBKDF2Parameters){ - .HMAC = HMAC, - .iterations = 1, - .salt = (unsigned char *)"salt", - .saltLength = 4, - .password = "password", - .passwordLength = 8, - .key = key, - .keyLength = 20, - .allowsSwappableMemory = true - })) && memcmp(key, "\x0C\x60\xC8\x0F\x96\x1F\x0E\x71\xF3\xA9\xB5" - "\x24\xAF\x60\x12\x06\x2F\xE0\x37\xA6", 20) == 0) - - TEST(@"PBKDF2-SHA1, 2 iterations", - R(OFPBKDF2((OFPBKDF2Parameters){ - .HMAC = HMAC, - .iterations = 2, - .salt = (unsigned char *)"salt", - .saltLength = 4, - .password = "password", - .passwordLength = 8, - .key = key, - .keyLength = 20, - .allowsSwappableMemory = true - })) && memcmp(key, "\xEA\x6C\x01\x4D\xC7\x2D\x6F\x8C\xCD\x1E\xD9" - "\x2A\xCE\x1D\x41\xF0\xD8\xDE\x89\x57", 20) == 0) - - TEST(@"PBKDF2-SHA1, 4096 iterations", - R(OFPBKDF2((OFPBKDF2Parameters){ - .HMAC = HMAC, - .iterations = 4096, - .salt = (unsigned char *)"salt", - .saltLength = 4, - .password = "password", - .passwordLength = 8, - .key = key, - .keyLength = 20, - .allowsSwappableMemory = true - })) && memcmp(key, "\x4B\x00\x79\x01\xB7\x65\x48\x9A\xBE\xAD\x49" - "\xD9\x26\xF7\x21\xD0\x65\xA4\x29\xC1", 20) == 0) - - /* This test takes too long, even on a fast machine. */ -#if 0 - TEST(@"PBKDF2-SHA1, 16777216 iterations", - R(OFPBKDF2((OFPBKDF2Parameters){ - .HMAC = HMAC, - .iterations = 16777216, - .salt = (unsigned char *)"salt", - .saltLength = 4, - .password = "password", - .passwordLength = 8, - .key = key, - .keyLength = 20, - .allowsSwappableMemory = true - })) && memcmp(key, "\xEE\xFE\x3D\x61\xCD\x4D\xA4\xE4\xE9\x94\x5B" - "\x3D\x6B\xA2\x15\x8C\x26\x34\xE9\x84", 20) == 0) -#endif - - TEST(@"PBKDF2-SHA1, 4096 iterations, key > 1 block", - R(OFPBKDF2((OFPBKDF2Parameters){ - .HMAC = HMAC, - .iterations = 4096, - .salt = (unsigned char *)"saltSALTsaltSALTsalt" - "SALTsaltSALTsalt", - .saltLength = 36, - .password = "passwordPASSWORDpassword", - .passwordLength = 24, - .key = key, - .keyLength = 25, - .allowsSwappableMemory = true - })) && - memcmp(key, "\x3D\x2E\xEC\x4F\xE4\x1C\x84\x9B\x80\xC8\xD8\x36\x62" - "\xC0\xE4\x4A\x8B\x29\x1A\x96\x4C\xF2\xF0\x70\x38", 25) == 0) - - TEST(@"PBKDF2-SHA1, 4096 iterations, key < 1 block", - R(OFPBKDF2((OFPBKDF2Parameters){ - .HMAC = HMAC, - .iterations = 4096, - .salt = (unsigned char *)"sa\0lt", - .saltLength = 5, - .password = "pass\0word", - .passwordLength = 9, - .key = key, - .keyLength = 16, - .allowsSwappableMemory = true - })) && memcmp(key, "\x56\xFA\x6A\xA7\x55\x48\x09\x9D\xCC\x37\xD7" - "\xF0\x34\x25\xE0\xC3", 16) == 0) - - objc_autoreleasePoolPop(pool); -} -@end Index: tests/RuntimeARCTests.m ================================================================== --- tests/RuntimeARCTests.m +++ tests/RuntimeARCTests.m @@ -15,11 +15,11 @@ #include "config.h" #import "TestsAppDelegate.h" -static OFString *module = @"Runtime (ARC)"; +static OFString *const module = @"Runtime (ARC)"; @interface RuntimeARCTest: OFObject @end @implementation RuntimeARCTest Index: tests/RuntimeTests.m ================================================================== --- tests/RuntimeTests.m +++ tests/RuntimeTests.m @@ -15,11 +15,11 @@ #include "config.h" #import "TestsAppDelegate.h" -static OFString *module = @"Runtime"; +static OFString *const module = @"Runtime"; @interface OFObject (SuperTest) - (id)superTest; @end @@ -61,33 +61,34 @@ @implementation TestsAppDelegate (RuntimeTests) - (void)runtimeTests { void *pool = objc_autoreleasePoolPush(); - RuntimeTest *rt = [[[RuntimeTest alloc] init] autorelease]; - OFString *t, *foo; + RuntimeTest *test = [[[RuntimeTest alloc] init] autorelease]; + OFString *string, *foo; #ifdef OF_OBJFW_RUNTIME - int cid1, cid2; + int classID; uintmax_t value; id object; #endif EXPECT_EXCEPTION(@"Calling a non-existent method via super", - OFNotImplementedException, [rt superTest]) + OFNotImplementedException, [test superTest]) TEST(@"Calling a method via a super with self == nil", - [rt nilSuperTest] == nil) + [test nilSuperTest] == nil) - t = [OFMutableString stringWithString: @"foo"]; + string = [OFMutableString stringWithString: @"foo"]; foo = @"foo"; - [rt setFoo: t]; - TEST(@"copy, nonatomic properties", [rt.foo isEqual: foo] && - rt.foo != foo && rt.foo.retainCount == 1) + test.foo = string; + TEST(@"copy, nonatomic properties", [test.foo isEqual: foo] && + test.foo != foo && test.foo.retainCount == 1) - rt.bar = t; - TEST(@"retain, atomic properties", rt.bar == t && t.retainCount == 3) + test.bar = string; + TEST(@"retain, atomic properties", + test.bar == string && string.retainCount == 3) #ifdef OF_OBJFW_RUNTIME if (sizeof(uintptr_t) == 8) value = 0xDEADBEEFDEADBEF; else if (sizeof(uintptr_t) == 4) @@ -94,18 +95,19 @@ value = 0xDEADBEF; else abort(); TEST(@"Tagged pointers", - (cid1 = objc_registerTaggedPointerClass([OFString class])) != -1 && - (cid2 = objc_registerTaggedPointerClass([OFNumber class])) != -1 && - (object = objc_createTaggedPointer(cid2, (uintptr_t)value)) && + objc_registerTaggedPointerClass([OFString class]) != -1 && + (classID = objc_registerTaggedPointerClass([OFNumber class])) != + -1 && + (object = objc_createTaggedPointer(classID, (uintptr_t)value)) && object_getClass(object) == [OFNumber class] && [object class] == [OFNumber class] && object_getTaggedPointerValue(object) == value && - objc_createTaggedPointer(cid2, UINTPTR_MAX >> 4) != nil && - objc_createTaggedPointer(cid2, (UINTPTR_MAX >> 4) + 1) == nil) + objc_createTaggedPointer(classID, UINTPTR_MAX >> 4) != nil && + objc_createTaggedPointer(classID, (UINTPTR_MAX >> 4) + 1) == nil) #endif objc_autoreleasePoolPop(pool); } @end DELETED tests/ScryptTests.m Index: tests/ScryptTests.m ================================================================== --- tests/ScryptTests.m +++ tests/ScryptTests.m @@ -1,217 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#include - -#import "TestsAppDelegate.h" - -static OFString *module = @"scrypt"; -/* Test vectors form RFC 7914 */ -static const unsigned char salsa20Input[64] = { - 0x7E, 0x87, 0x9A, 0x21, 0x4F, 0x3E, 0xC9, 0x86, 0x7C, 0xA9, 0x40, 0xE6, - 0x41, 0x71, 0x8F, 0x26, 0xBA, 0xEE, 0x55, 0x5B, 0x8C, 0x61, 0xC1, 0xB5, - 0x0D, 0xF8, 0x46, 0x11, 0x6D, 0xCD, 0x3B, 0x1D, 0xEE, 0x24, 0xF3, 0x19, - 0xDF, 0x9B, 0x3D, 0x85, 0x14, 0x12, 0x1E, 0x4B, 0x5A, 0xC5, 0xAA, 0x32, - 0x76, 0x02, 0x1D, 0x29, 0x09, 0xC7, 0x48, 0x29, 0xED, 0xEB, 0xC6, 0x8D, - 0xB8, 0xB8, 0xC2, 0x5E -}; -static const unsigned char salsa20Output[64] = { - 0xA4, 0x1F, 0x85, 0x9C, 0x66, 0x08, 0xCC, 0x99, 0x3B, 0x81, 0xCA, 0xCB, - 0x02, 0x0C, 0xEF, 0x05, 0x04, 0x4B, 0x21, 0x81, 0xA2, 0xFD, 0x33, 0x7D, - 0xFD, 0x7B, 0x1C, 0x63, 0x96, 0x68, 0x2F, 0x29, 0xB4, 0x39, 0x31, 0x68, - 0xE3, 0xC9, 0xE6, 0xBC, 0xFE, 0x6B, 0xC5, 0xB7, 0xA0, 0x6D, 0x96, 0xBA, - 0xE4, 0x24, 0xCC, 0x10, 0x2C, 0x91, 0x74, 0x5C, 0x24, 0xAD, 0x67, 0x3D, - 0xC7, 0x61, 0x8F, 0x81 -}; -static const union { - unsigned char uc[128]; - uint32_t u32[32]; -} blockMixInput = { .uc = { - 0xF7, 0xCE, 0x0B, 0x65, 0x3D, 0x2D, 0x72, 0xA4, 0x10, 0x8C, 0xF5, 0xAB, - 0xE9, 0x12, 0xFF, 0xDD, 0x77, 0x76, 0x16, 0xDB, 0xBB, 0x27, 0xA7, 0x0E, - 0x82, 0x04, 0xF3, 0xAE, 0x2D, 0x0F, 0x6F, 0xAD, 0x89, 0xF6, 0x8F, 0x48, - 0x11, 0xD1, 0xE8, 0x7B, 0xCC, 0x3B, 0xD7, 0x40, 0x0A, 0x9F, 0xFD, 0x29, - 0x09, 0x4F, 0x01, 0x84, 0x63, 0x95, 0x74, 0xF3, 0x9A, 0xE5, 0xA1, 0x31, - 0x52, 0x17, 0xBC, 0xD7, - 0x89, 0x49, 0x91, 0x44, 0x72, 0x13, 0xBB, 0x22, 0x6C, 0x25, 0xB5, 0x4D, - 0xA8, 0x63, 0x70, 0xFB, 0xCD, 0x98, 0x43, 0x80, 0x37, 0x46, 0x66, 0xBB, - 0x8F, 0xFC, 0xB5, 0xBF, 0x40, 0xC2, 0x54, 0xB0, 0x67, 0xD2, 0x7C, 0x51, - 0xCE, 0x4A, 0xD5, 0xFE, 0xD8, 0x29, 0xC9, 0x0B, 0x50, 0x5A, 0x57, 0x1B, - 0x7F, 0x4D, 0x1C, 0xAD, 0x6A, 0x52, 0x3C, 0xDA, 0x77, 0x0E, 0x67, 0xBC, - 0xEA, 0xAF, 0x7E, 0x89 -}}; -static const unsigned char blockMixOutput[128] = { - 0xA4, 0x1F, 0x85, 0x9C, 0x66, 0x08, 0xCC, 0x99, 0x3B, 0x81, 0xCA, 0xCB, - 0x02, 0x0C, 0xEF, 0x05, 0x04, 0x4B, 0x21, 0x81, 0xA2, 0xFD, 0x33, 0x7D, - 0xFD, 0x7B, 0x1C, 0x63, 0x96, 0x68, 0x2F, 0x29, 0xB4, 0x39, 0x31, 0x68, - 0xE3, 0xC9, 0xE6, 0xBC, 0xFE, 0x6B, 0xC5, 0xB7, 0xA0, 0x6D, 0x96, 0xBA, - 0xE4, 0x24, 0xCC, 0x10, 0x2C, 0x91, 0x74, 0x5C, 0x24, 0xAD, 0x67, 0x3D, - 0xC7, 0x61, 0x8F, 0x81, - 0x20, 0xED, 0xC9, 0x75, 0x32, 0x38, 0x81, 0xA8, 0x05, 0x40, 0xF6, 0x4C, - 0x16, 0x2D, 0xCD, 0x3C, 0x21, 0x07, 0x7C, 0xFE, 0x5F, 0x8D, 0x5F, 0xE2, - 0xB1, 0xA4, 0x16, 0x8F, 0x95, 0x36, 0x78, 0xB7, 0x7D, 0x3B, 0x3D, 0x80, - 0x3B, 0x60, 0xE4, 0xAB, 0x92, 0x09, 0x96, 0xE5, 0x9B, 0x4D, 0x53, 0xB6, - 0x5D, 0x2A, 0x22, 0x58, 0x77, 0xD5, 0xED, 0xF5, 0x84, 0x2C, 0xB9, 0xF1, - 0x4E, 0xEF, 0xE4, 0x25 -}; -static const unsigned char ROMixInput[128] = { - 0xF7, 0xCE, 0x0B, 0x65, 0x3D, 0x2D, 0x72, 0xA4, 0x10, 0x8C, 0xF5, 0xAB, - 0xE9, 0x12, 0xFF, 0xDD, 0x77, 0x76, 0x16, 0xDB, 0xBB, 0x27, 0xA7, 0x0E, - 0x82, 0x04, 0xF3, 0xAE, 0x2D, 0x0F, 0x6F, 0xAD, 0x89, 0xF6, 0x8F, 0x48, - 0x11, 0xD1, 0xE8, 0x7B, 0xCC, 0x3B, 0xD7, 0x40, 0x0A, 0x9F, 0xFD, 0x29, - 0x09, 0x4F, 0x01, 0x84, 0x63, 0x95, 0x74, 0xF3, 0x9A, 0xE5, 0xA1, 0x31, - 0x52, 0x17, 0xBC, 0xD7, 0x89, 0x49, 0x91, 0x44, 0x72, 0x13, 0xBB, 0x22, - 0x6C, 0x25, 0xB5, 0x4D, 0xA8, 0x63, 0x70, 0xFB, 0xCD, 0x98, 0x43, 0x80, - 0x37, 0x46, 0x66, 0xBB, 0x8F, 0xFC, 0xB5, 0xBF, 0x40, 0xC2, 0x54, 0xB0, - 0x67, 0xD2, 0x7C, 0x51, 0xCE, 0x4A, 0xD5, 0xFE, 0xD8, 0x29, 0xC9, 0x0B, - 0x50, 0x5A, 0x57, 0x1B, 0x7F, 0x4D, 0x1C, 0xAD, 0x6A, 0x52, 0x3C, 0xDA, - 0x77, 0x0E, 0x67, 0xBC, 0xEA, 0xAF, 0x7E, 0x89 -}; -static const unsigned char ROMixOutput[128] = { - 0x79, 0xCC, 0xC1, 0x93, 0x62, 0x9D, 0xEB, 0xCA, 0x04, 0x7F, 0x0B, 0x70, - 0x60, 0x4B, 0xF6, 0xB6, 0x2C, 0xE3, 0xDD, 0x4A, 0x96, 0x26, 0xE3, 0x55, - 0xFA, 0xFC, 0x61, 0x98, 0xE6, 0xEA, 0x2B, 0x46, 0xD5, 0x84, 0x13, 0x67, - 0x3B, 0x99, 0xB0, 0x29, 0xD6, 0x65, 0xC3, 0x57, 0x60, 0x1F, 0xB4, 0x26, - 0xA0, 0xB2, 0xF4, 0xBB, 0xA2, 0x00, 0xEE, 0x9F, 0x0A, 0x43, 0xD1, 0x9B, - 0x57, 0x1A, 0x9C, 0x71, 0xEF, 0x11, 0x42, 0xE6, 0x5D, 0x5A, 0x26, 0x6F, - 0xDD, 0xCA, 0x83, 0x2C, 0xE5, 0x9F, 0xAA, 0x7C, 0xAC, 0x0B, 0x9C, 0xF1, - 0xBE, 0x2B, 0xFF, 0xCA, 0x30, 0x0D, 0x01, 0xEE, 0x38, 0x76, 0x19, 0xC4, - 0xAE, 0x12, 0xFD, 0x44, 0x38, 0xF2, 0x03, 0xA0, 0xE4, 0xE1, 0xC4, 0x7E, - 0xC3, 0x14, 0x86, 0x1F, 0x4E, 0x90, 0x87, 0xCB, 0x33, 0x39, 0x6A, 0x68, - 0x73, 0xE8, 0xF9, 0xD2, 0x53, 0x9A, 0x4B, 0x8E -}; -static const unsigned char testVector1[64] = { - 0x77, 0xD6, 0x57, 0x62, 0x38, 0x65, 0x7B, 0x20, 0x3B, 0x19, 0xCA, 0x42, - 0xC1, 0x8A, 0x04, 0x97, 0xF1, 0x6B, 0x48, 0x44, 0xE3, 0x07, 0x4A, 0xE8, - 0xDF, 0xDF, 0xFA, 0x3F, 0xED, 0xE2, 0x14, 0x42, 0xFC, 0xD0, 0x06, 0x9D, - 0xED, 0x09, 0x48, 0xF8, 0x32, 0x6A, 0x75, 0x3A, 0x0F, 0xC8, 0x1F, 0x17, - 0xE8, 0xD3, 0xE0, 0xFB, 0x2E, 0x0D, 0x36, 0x28, 0xCF, 0x35, 0xE2, 0x0C, - 0x38, 0xD1, 0x89, 0x06 -}; -static const unsigned char testVector2[64] = { - 0xFD, 0xBA, 0xBE, 0x1C, 0x9D, 0x34, 0x72, 0x00, 0x78, 0x56, 0xE7, 0x19, - 0x0D, 0x01, 0xE9, 0xFE, 0x7C, 0x6A, 0xD7, 0xCB, 0xC8, 0x23, 0x78, 0x30, - 0xE7, 0x73, 0x76, 0x63, 0x4B, 0x37, 0x31, 0x62, 0x2E, 0xAF, 0x30, 0xD9, - 0x2E, 0x22, 0xA3, 0x88, 0x6F, 0xF1, 0x09, 0x27, 0x9D, 0x98, 0x30, 0xDA, - 0xC7, 0x27, 0xAF, 0xB9, 0x4A, 0x83, 0xEE, 0x6D, 0x83, 0x60, 0xCB, 0xDF, - 0xA2, 0xCC, 0x06, 0x40 -}; -static const unsigned char testVector3[64] = { - 0x70, 0x23, 0xBD, 0xCB, 0x3A, 0xFD, 0x73, 0x48, 0x46, 0x1C, 0x06, 0xCD, - 0x81, 0xFD, 0x38, 0xEB, 0xFD, 0xA8, 0xFB, 0xBA, 0x90, 0x4F, 0x8E, 0x3E, - 0xA9, 0xB5, 0x43, 0xF6, 0x54, 0x5D, 0xA1, 0xF2, 0xD5, 0x43, 0x29, 0x55, - 0x61, 0x3F, 0x0F, 0xCF, 0x62, 0xD4, 0x97, 0x05, 0x24, 0x2A, 0x9A, 0xF9, - 0xE6, 0x1E, 0x85, 0xDC, 0x0D, 0x65, 0x1E, 0x40, 0xDF, 0xCF, 0x01, 0x7B, - 0x45, 0x57, 0x58, 0x87 -}; -/* The forth test vector is too expensive to include it in the tests. */ -#if 0 -static const unsigned char testVector4[64] = { - 0x21, 0x01, 0xCB, 0x9B, 0x6A, 0x51, 0x1A, 0xAE, 0xAD, 0xDB, 0xBE, 0x09, - 0xCF, 0x70, 0xF8, 0x81, 0xEC, 0x56, 0x8D, 0x57, 0x4A, 0x2F, 0xFD, 0x4D, - 0xAB, 0xE5, 0xEE, 0x98, 0x20, 0xAD, 0xAA, 0x47, 0x8E, 0x56, 0xFD, 0x8F, - 0x4B, 0xA5, 0xD0, 0x9F, 0xFA, 0x1C, 0x6D, 0x92, 0x7C, 0x40, 0xF4, 0xC3, - 0x37, 0x30, 0x40, 0x49, 0xE8, 0xA9, 0x52, 0xFB, 0xCB, 0xF4, 0x5C, 0x6F, - 0xA7, 0x7A, 0x41, 0xA4 -}; -#endif - -@implementation TestsAppDelegate (ScryptTests) -- (void)scryptTests -{ - void *pool = objc_autoreleasePoolPush(); - uint32_t salsa20Buffer[16]; - uint32_t blockMixBuffer[32]; - uint32_t ROMixBuffer[32], ROMixTmp[17 * 32]; - unsigned char output[64]; - - TEST(@"Salsa20/8 Core", - R(memcpy(salsa20Buffer, salsa20Input, 64)) && - R(OFSalsa20_8Core(salsa20Buffer)) && - memcmp(salsa20Buffer, salsa20Output, 64) == 0) - - TEST(@"Block mix", - R(OFScryptBlockMix(blockMixBuffer, blockMixInput.u32, 1)) && - memcmp(blockMixBuffer, blockMixOutput, 128) == 0) - - TEST(@"ROMix", - R(memcpy(ROMixBuffer, ROMixInput, 128)) && - R(OFScryptROMix(ROMixBuffer, 1, 16, ROMixTmp)) && - memcmp(ROMixBuffer, ROMixOutput, 128) == 0) - - TEST(@"scrypt test vector #1", - R(OFScrypt((OFScryptParameters){ - .blockSize = 1, - .costFactor = 16, - .parallelization = 1, - .salt = (unsigned char *)"", - .saltLength = 0, - .password = "", - .passwordLength = 0, - .key = output, - .keyLength = 64, - .allowsSwappableMemory = true - })) && memcmp(output, testVector1, 64) == 0) - - TEST(@"scrypt test vector #2", - R(OFScrypt((OFScryptParameters){ - .blockSize = 8, - .costFactor = 1024, - .parallelization = 16, - .salt = (unsigned char *)"NaCl", - .saltLength = 4, - .password = "password", - .passwordLength = 8, - .key = output, - .keyLength = 64, - .allowsSwappableMemory = true - })) && memcmp(output, testVector2, 64) == 0) - - TEST(@"scrypt test vector #3", - R(OFScrypt((OFScryptParameters){ - .blockSize = 8, - .costFactor = 16384, - .parallelization = 1, - .salt = (unsigned char *)"SodiumChloride", - .saltLength = 14, - .password = "pleaseletmein", - .passwordLength = 13, - .key = output, - .keyLength = 64, - .allowsSwappableMemory = true - })) && memcmp(output, testVector3, 64) == 0) - - /* The forth test vector is too expensive to include it in the tests. */ -#if 0 - TEST(@"scrypt test vector #4", - R(OFScrypt((OFScryptParameters){ - .blockSize = 8, - .costFactor = 1048576, - .parallelization = 1, - .salt = (unsigned char *)"SodiumChloride", - .saltLength = 14, - .password = "pleaseletmein", - .passwordLength = 13, - .key = output, - .keyLength = 64, - .allowsSwappableMemory = true - })) && memcmp(output, testVector4, 64) == 0) -#endif - - objc_autoreleasePoolPop(pool); -} -@end DELETED tests/SocketTests.m Index: tests/SocketTests.m ================================================================== --- tests/SocketTests.m +++ tests/SocketTests.m @@ -1,199 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#import "TestsAppDelegate.h" - -#define COMPARE_V6(a, a0, a1, a2, a3, a4, a5, a6, a7) \ - (a.sockaddr.in6.sin6_addr.s6_addr[0] == (a0 >> 8) && \ - a.sockaddr.in6.sin6_addr.s6_addr[1] == (a0 & 0xFF) && \ - a.sockaddr.in6.sin6_addr.s6_addr[2] == (a1 >> 8) && \ - a.sockaddr.in6.sin6_addr.s6_addr[3] == (a1 & 0xFF) && \ - a.sockaddr.in6.sin6_addr.s6_addr[4] == (a2 >> 8) && \ - a.sockaddr.in6.sin6_addr.s6_addr[5] == (a2 & 0xFF) && \ - a.sockaddr.in6.sin6_addr.s6_addr[6] == (a3 >> 8) && \ - a.sockaddr.in6.sin6_addr.s6_addr[7] == (a3 & 0xFF) && \ - a.sockaddr.in6.sin6_addr.s6_addr[8] == (a4 >> 8) && \ - a.sockaddr.in6.sin6_addr.s6_addr[9] == (a4 & 0xFF) && \ - a.sockaddr.in6.sin6_addr.s6_addr[10] == (a5 >> 8) && \ - a.sockaddr.in6.sin6_addr.s6_addr[11] == (a5 & 0xFF) && \ - a.sockaddr.in6.sin6_addr.s6_addr[12] == (a6 >> 8) && \ - a.sockaddr.in6.sin6_addr.s6_addr[13] == (a6 & 0xFF) && \ - a.sockaddr.in6.sin6_addr.s6_addr[14] == (a7 >> 8) && \ - a.sockaddr.in6.sin6_addr.s6_addr[15] == (a7 & 0xFF)) -#define SET_V6(a, a0, a1, a2, a3, a4, a5, a6, a7) \ - a.sockaddr.in6.sin6_addr.s6_addr[0] = a0 >> 8; \ - a.sockaddr.in6.sin6_addr.s6_addr[1] = a0 & 0xFF; \ - a.sockaddr.in6.sin6_addr.s6_addr[2] = a1 >> 8; \ - a.sockaddr.in6.sin6_addr.s6_addr[3] = a1 & 0xFF; \ - a.sockaddr.in6.sin6_addr.s6_addr[4] = a2 >> 8; \ - a.sockaddr.in6.sin6_addr.s6_addr[5] = a2 & 0xFF; \ - a.sockaddr.in6.sin6_addr.s6_addr[6] = a3 >> 8; \ - a.sockaddr.in6.sin6_addr.s6_addr[7] = a3 & 0xFF; \ - a.sockaddr.in6.sin6_addr.s6_addr[8] = a4 >> 8; \ - a.sockaddr.in6.sin6_addr.s6_addr[9] = a4 & 0xFF; \ - a.sockaddr.in6.sin6_addr.s6_addr[10] = a5 >> 8; \ - a.sockaddr.in6.sin6_addr.s6_addr[11] = a5 & 0xFF; \ - a.sockaddr.in6.sin6_addr.s6_addr[12] = a6 >> 8; \ - a.sockaddr.in6.sin6_addr.s6_addr[13] = a6 & 0xFF; \ - a.sockaddr.in6.sin6_addr.s6_addr[14] = a7 >> 8; \ - a.sockaddr.in6.sin6_addr.s6_addr[15] = a7 & 0xFF; - -static OFString *module = @"Socket"; - -@implementation TestsAppDelegate (SocketTests) -- (void)socketTests -{ - void *pool = objc_autoreleasePoolPush(); - OFSocketAddress addr; - - TEST(@"Parsing an IPv4", - R(addr = OFSocketAddressParseIP(@"127.0.0.1", 1234)) && - OFFromBigEndian32(addr.sockaddr.in.sin_addr.s_addr) == 0x7F000001 && - OFFromBigEndian16(addr.sockaddr.in.sin_port) == 1234) - - EXPECT_EXCEPTION(@"Refusing invalid IPv4 #1", OFInvalidFormatException, - OFSocketAddressParseIP(@"127.0.0.0.1", 1234)) - - EXPECT_EXCEPTION(@"Refusing invalid IPv4 #2", OFInvalidFormatException, - OFSocketAddressParseIP(@"127.0.0.256", 1234)) - - EXPECT_EXCEPTION(@"Refusing invalid IPv4 #3", OFInvalidFormatException, - OFSocketAddressParseIP(@"127.0.0. 1", 1234)) - - EXPECT_EXCEPTION(@"Refusing invalid IPv4 #4", OFInvalidFormatException, - OFSocketAddressParseIP(@" 127.0.0.1", 1234)) - - EXPECT_EXCEPTION(@"Refusing invalid IPv4 #5", OFInvalidFormatException, - OFSocketAddressParseIP(@"127.0.a.1", 1234)) - - EXPECT_EXCEPTION(@"Refusing invalid IPv4 #6", OFInvalidFormatException, - OFSocketAddressParseIP(@"127.0..1", 1234)) - - TEST(@"Port of an IPv4 address", OFSocketAddressPort(&addr) == 1234) - - TEST(@"Converting an IPv4 to a string", - [OFSocketAddressString(&addr) isEqual: @"127.0.0.1"]) - - TEST(@"Parsing an IPv6 #1", - R(addr = OFSocketAddressParseIP( - @"1122:3344:5566:7788:99aa:bbCc:ddee:ff00", 1234)) && - COMPARE_V6(addr, - 0x1122, 0x3344, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0xDDEE, 0xFF00) && - OFFromBigEndian16(addr.sockaddr.in6.sin6_port) == 1234) - - TEST(@"Parsing an IPv6 #2", - R(addr = OFSocketAddressParseIP(@"::", 1234)) && - COMPARE_V6(addr, 0, 0, 0, 0, 0, 0, 0, 0) && - OFFromBigEndian16(addr.sockaddr.in6.sin6_port) == 1234) - - TEST(@"Parsing an IPv6 #3", - R(addr = OFSocketAddressParseIP(@"aaAa::bBbb", 1234)) && - COMPARE_V6(addr, 0xAAAA, 0, 0, 0, 0, 0, 0, 0xBBBB) && - OFFromBigEndian16(addr.sockaddr.in6.sin6_port) == 1234) - - TEST(@"Parsing an IPv6 #4", - R(addr = OFSocketAddressParseIP(@"aaAa::", 1234)) && - COMPARE_V6(addr, 0xAAAA, 0, 0, 0, 0, 0, 0, 0) && - OFFromBigEndian16(addr.sockaddr.in6.sin6_port) == 1234) - - TEST(@"Parsing an IPv6 #5", - R(addr = OFSocketAddressParseIP(@"::aaAa", 1234)) && - COMPARE_V6(addr, 0, 0, 0, 0, 0, 0, 0, 0xAAAA) && - OFFromBigEndian16(addr.sockaddr.in6.sin6_port) == 1234) - - EXPECT_EXCEPTION(@"Refusing invalid IPv6 #1", OFInvalidFormatException, - OFSocketAddressParseIP(@"1:::2", 1234)) - - EXPECT_EXCEPTION(@"Refusing invalid IPv6 #2", OFInvalidFormatException, - OFSocketAddressParseIP(@"1: ::2", 1234)) - - EXPECT_EXCEPTION(@"Refusing invalid IPv6 #3", OFInvalidFormatException, - OFSocketAddressParseIP(@"1:: :2", 1234)) - - EXPECT_EXCEPTION(@"Refusing invalid IPv6 #4", OFInvalidFormatException, - OFSocketAddressParseIP(@"1::2::3", 1234)) - - EXPECT_EXCEPTION(@"Refusing invalid IPv6 #5", OFInvalidFormatException, - OFSocketAddressParseIP(@"10000::1", 1234)) - - EXPECT_EXCEPTION(@"Refusing invalid IPv6 #6", OFInvalidFormatException, - OFSocketAddressParseIP(@"::10000", 1234)) - - EXPECT_EXCEPTION(@"Refusing invalid IPv6 #7", OFInvalidFormatException, - OFSocketAddressParseIP(@"::1::", 1234)) - - EXPECT_EXCEPTION(@"Refusing invalid IPv6 #8", OFInvalidFormatException, - OFSocketAddressParseIP(@"1:2:3:4:5:6:7:", 1234)) - - EXPECT_EXCEPTION(@"Refusing invalid IPv6 #9", OFInvalidFormatException, - OFSocketAddressParseIP(@"1:2:3:4:5:6:7::", 1234)) - - EXPECT_EXCEPTION(@"Refusing invalid IPv6 #10", OFInvalidFormatException, - OFSocketAddressParseIP(@"1:2", 1234)) - - TEST(@"Port of an IPv6 address", OFSocketAddressPort(&addr) == 1234) - - SET_V6(addr, 0, 0, 0, 0, 0, 0, 0, 0) - TEST(@"Converting an IPv6 to a string #1", - [OFSocketAddressString(&addr) isEqual: @"::"]) - - SET_V6(addr, 0, 0, 0, 0, 0, 0, 0, 1) - TEST(@"Converting an IPv6 to a string #2", - [OFSocketAddressString(&addr) isEqual: @"::1"]) - - SET_V6(addr, 1, 0, 0, 0, 0, 0, 0, 0) - TEST(@"Converting an IPv6 to a string #3", - [OFSocketAddressString(&addr) isEqual: @"1::"]) - - SET_V6(addr, - 0x1122, 0x3344, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0xDDEE, 0xFF00) - TEST(@"Converting an IPv6 to a string #4", - [OFSocketAddressString(&addr) - isEqual: @"1122:3344:5566:7788:99aa:bbcc:ddee:ff00"]) - - SET_V6(addr, 0x1122, 0x3344, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0xDDEE, 0) - TEST(@"Converting an IPv6 to a string #5", - [OFSocketAddressString(&addr) - isEqual: @"1122:3344:5566:7788:99aa:bbcc:ddee:0"]) - - SET_V6(addr, 0x1122, 0x3344, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0, 0) - TEST(@"Converting an IPv6 to a string #6", - [OFSocketAddressString(&addr) - isEqual: @"1122:3344:5566:7788:99aa:bbcc::"]) - - SET_V6(addr, 0, 0x3344, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0xDDEE, 0xFF00) - TEST(@"Converting an IPv6 to a string #7", - [OFSocketAddressString(&addr) - isEqual: @"0:3344:5566:7788:99aa:bbcc:ddee:ff00"]) - - SET_V6(addr, 0, 0, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0xDDEE, 0xFF00) - TEST(@"Converting an IPv6 to a string #8", - [OFSocketAddressString(&addr) - isEqual: @"::5566:7788:99aa:bbcc:ddee:ff00"]) - - SET_V6(addr, 0, 0, 0x5566, 0, 0, 0, 0xDDEE, 0xFF00) - TEST(@"Converting an IPv6 to a string #9", - [OFSocketAddressString(&addr) isEqual: @"0:0:5566::ddee:ff00"]) - - SET_V6(addr, 0, 0, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0, 0) - TEST(@"Converting an IPv6 to a string #10", - [OFSocketAddressString(&addr) - isEqual: @"::5566:7788:99aa:bbcc:0:0"]) - - objc_autoreleasePoolPop(pool); -} -@end Index: tests/TestsAppDelegate.h ================================================================== --- tests/TestsAppDelegate.h +++ tests/TestsAppDelegate.h @@ -144,10 +144,14 @@ @end @interface TestsAppDelegate (OFObjectTests) - (void)objectTests; @end + +@interface TestsAppDelegate (OFPBKDF2Tests) +- (void)PBKDF2Tests; +@end @interface TestsAppDelegate (OFPropertyListTests) - (void)propertyListTests; @end @@ -165,11 +169,11 @@ @interface TestsAppDelegate (OFRIPEMD160HashTests) - (void)RIPEMD160HashTests; @end -@interface TestsAppDelegate (ScryptTests) +@interface TestsAppDelegate (OFScryptTests) - (void)scryptTests; @end @interface TestsAppDelegate (OFSHA1HashTests) - (void)SHA1HashTests; @@ -212,10 +216,14 @@ @end @interface TestsAppDelegate (OFHMACTests) - (void)HMACTests; @end + +@interface TestsAppDelegate (OFSocketTests) +- (void)socketTests; +@end @interface TestsAppDelegate (OFStreamTests) - (void)streamTests; @end @@ -257,13 +265,5 @@ @interface TestsAppDelegate (OFXMLParserTests) - (void)XMLParserTests; @end - -@interface TestsAppDelegate (PBKDF2Tests) -- (void)PBKDF2Tests; -@end - -@interface TestsAppDelegate (SocketTests) -- (void)socketTests; -@end Index: tests/TestsAppDelegate.m ================================================================== --- tests/TestsAppDelegate.m +++ tests/TestsAppDelegate.m @@ -53,22 +53,22 @@ extern unsigned long OFHashSeed; #ifdef OF_PSP static int -exit_cb(int arg1, int arg2, void *arg) +exitCallback(int arg1, int arg2, void *arg) { sceKernelExitGame(); return 0; } static int -callback_thread(SceSize args, void *argp) +threadCallback(SceSize args, void *argp) { sceKernelRegisterExitCallback( - sceKernelCreateCallback("Exit Callback", exit_cb, NULL)); + sceKernelCreateCallback("Exit Callback", exitCallback, NULL)); sceKernelSleepThreadCB(); return 0; } #endif @@ -83,14 +83,14 @@ #if defined(OF_OBJFW_RUNTIME) && !defined(OF_WINDOWS) && !defined(OF_AMIGAOS) /* * This does not work on Win32 if ObjFW is built as a DLL. * * On AmigaOS, some destructors need to be able to send messages. - * Calling objc_exit() via atexit() would result in the runtime being + * Calling objc_deinit() via atexit() would result in the runtime being * destructed before for the destructors ran. */ - atexit(objc_exit); + atexit(objc_deinit); #endif /* We need deterministic hashes for tests */ OFHashSeed = 0; @@ -120,11 +120,11 @@ pspDebugScreenInit(); sceCtrlSetSamplingCycle(0); sceCtrlSetSamplingMode(PSP_CTRL_MODE_DIGITAL); - if ((tid = sceKernelCreateThread("update_thread", callback_thread, + if ((tid = sceKernelCreateThread("update_thread", threadCallback, 0x11, 0xFA0, 0, 0)) >= 0) sceKernelStartThread(tid, 0, 0); #endif #ifdef OF_NINTENDO_DS @@ -198,33 +198,30 @@ return OFApplicationMain(&argc, &argv, [[TestsAppDelegate alloc] init]); #endif } @implementation TestsAppDelegate -- (void)outputTesting: (OFString *)test - inModule: (OFString *)module +- (void)outputTesting: (OFString *)test inModule: (OFString *)module { if (OFStdOut.hasTerminal) { [OFStdOut setForegroundColor: [OFColor yellow]]; [OFStdOut writeFormat: @"[%@] %@: testing...", module, test]; } else [OFStdOut writeFormat: @"[%@] %@: ", module, test]; } -- (void)outputSuccess: (OFString *)test - inModule: (OFString *)module +- (void)outputSuccess: (OFString *)test inModule: (OFString *)module { if (OFStdOut.hasTerminal) { [OFStdOut setForegroundColor: [OFColor lime]]; [OFStdOut eraseLine]; [OFStdOut writeFormat: @"\r[%@] %@: ok\n", module, test]; } else [OFStdOut writeLine: @"ok"]; } -- (void)outputFailure: (OFString *)test - inModule: (OFString *)module +- (void)outputFailure: (OFString *)test inModule: (OFString *)module { if (OFStdOut.hasTerminal) { [OFStdOut setForegroundColor: [OFColor red]]; [OFStdOut eraseLine]; [OFStdOut writeFormat: @"\r[%@] %@: failed\n", module, test]; Index: tests/objc_sync/Makefile ================================================================== --- tests/objc_sync/Makefile +++ tests/objc_sync/Makefile @@ -9,25 +9,27 @@ .PHONY: run run: rm -f libobjfw.so.${OBJFW_LIB_MAJOR} rm -f libobjfw.so.${OBJFW_LIB_MAJOR_MINOR} - rm -f objfw.dll libobjfw.${OBJFW_LIB_MAJOR}.dylib + rm -f objfw${OBJFW_LIB_MAJOR}.dll libobjfw.${OBJFW_LIB_MAJOR}.dylib rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR} rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR} - rm -f objfwrt.dll libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib + rm -f objfwrt${OBJFWRT_LIB_MAJOR}.dll + rm -f libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib rm -f ${OBJFWRT_AMIGA_LIB} if test -f ../../src/libobjfw.so; then \ ${LN_S} ../../src/libobjfw.so libobjfw.so.${OBJFW_LIB_MAJOR}; \ ${LN_S} ../../src/libobjfw.so \ libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; \ elif test -f ../../src/libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; then \ ${LN_S} ../../src/libobjfw.so.${OBJFW_LIB_MAJOR_MINOR} \ libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; \ fi - if test -f ../../src/objfw.dll; then \ - ${LN_S} ../../src/objfw.dll objfw.dll; \ + if test -f ../../src/objfw${OBJFW_LIB_MAJOR}.dll; then \ + ${LN_S} ../../src/objfw${OBJFW_LIB_MAJOR}.dll \ + objfw${OBJFW_LIB_MAJOR}.dll; \ fi if test -f ../../src/libobjfw.dylib; then \ ${LN_S} ../../src/libobjfw.dylib \ libobjfw.${OBJFW_LIB_MAJOR}.dylib; \ fi @@ -37,12 +39,13 @@ ${LN_S} ../../src/runtime/libobjfwrt.so \ libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; \ elif test -f ../../src/runtime/libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; then \ ${LN_S} ../../src/runtime/libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR} libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; \ fi - if test -f ../../src/runtime/objfwrt.dll; then \ - ${LN_S} ../../src/runtime/objfwrt.dll objfwrt.dll; \ + if test -f ../../src/runtime/objfwrt${OBJFWRT_LIB_MAJOR}.dll; then \ + ${LN_S} ../../src/runtime/objfwrt${OBJFWRT_LIB_MAJOR}.dll \ + objfwrt${OBJFWRT_LIB_MAJOR}.dll; \ fi if test -f ../../src/runtime/libobjfwrt.dylib; then \ ${LN_S} ../../src/runtime/libobjfwrt.dylib \ libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib; \ fi @@ -53,15 +56,17 @@ LD_LIBRARY_PATH=.$${LD_LIBRARY_PATH+:}$$LD_LIBRARY_PATH \ DYLD_LIBRARY_PATH=.$${DYLD_LIBRARY_PATH+:}$$DYLD_LIBRARY_PATH \ LIBRARY_PATH=.$${LIBRARY_PATH+:}$$LIBRARY_PATH \ ${WRAPPER} ./${PROG_NOINST}; EXIT=$$?; \ rm -f libobjfw.so.${OBJFW_LIB_MAJOR}; \ - rm -f objfw.so.${OBJFW_LIB_MAJOR_MINOR} objfw.dll; \ + rm -f libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; \ + rm -f objfw${OBJFW_LIB_MAJOR}.dll; \ rm -f libobjfw.${OBJFW_LIB_MAJOR}.dylib; \ rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR}; \ - rm -f objfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR} objfwrt.dll; \ + rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; \ + rm -f objfwrt${OBJFWRT_LIB_MAJOR}.dll; \ rm -f libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib; \ exit $$EXIT CPPFLAGS += -I../../src -I../../src/runtime -I../.. LIBS := -L../../src -lobjfw -L../../src/runtime ${RUNTIME_LIBS} ${LIBS} LD = ${OBJC} Index: tests/plugin/TestPlugin.m ================================================================== --- tests/plugin/TestPlugin.m +++ tests/plugin/TestPlugin.m @@ -26,16 +26,16 @@ if (class == Nil) /* * musl has broken dlclose(): Instead of calling the destructor * on dlclose(), they call it on exit(). This of course means - * that our tests might have already called objc_exit() and the - * class is already gone. + * that our tests might have already called objc_deinit() and + * the class is already gone. */ return; - objc_unregister_class(class); + objc_unregisterClass(class); } #endif @implementation TestPlugin - (int)test: (int)num Index: tests/terminal/Makefile ================================================================== --- tests/terminal/Makefile +++ tests/terminal/Makefile @@ -9,25 +9,27 @@ .PHONY: run run: rm -f libobjfw.so.${OBJFW_LIB_MAJOR} rm -f libobjfw.so.${OBJFW_LIB_MAJOR_MINOR} - rm -f objfw.dll libobjfw.${OBJFW_LIB_MAJOR}.dylib + rm -f objfw${OBJFW_LIB_MAJOR}.dll libobjfw.${OBJFW_LIB_MAJOR}.dylib rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR} rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR} - rm -f objfwrt.dll libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib + rm -f objfwrt${OBJFWRT_LIB_MAJOR}.dll + rm -f libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib rm -f ${OBJFWRT_AMIGA_LIB} if test -f ../../src/libobjfw.so; then \ ${LN_S} ../../src/libobjfw.so libobjfw.so.${OBJFW_LIB_MAJOR}; \ ${LN_S} ../../src/libobjfw.so \ libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; \ elif test -f ../../src/libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; then \ ${LN_S} ../../src/libobjfw.so.${OBJFW_LIB_MAJOR_MINOR} \ libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; \ fi - if test -f ../../src/objfw.dll; then \ - ${LN_S} ../../src/objfw.dll objfw.dll; \ + if test -f ../../src/objfw${OBJFW_LIB_MAJOR}.dll; then \ + ${LN_S} ../../src/objfw${OBJFW_LIB_MAJOR}.dll \ + objfw${OBJFW_LIB_MAJOR}.dll; \ fi if test -f ../../src/libobjfw.dylib; then \ ${LN_S} ../../src/libobjfw.dylib \ libobjfw.${OBJFW_LIB_MAJOR}.dylib; \ fi @@ -37,12 +39,13 @@ ${LN_S} ../../src/runtime/libobjfwrt.so \ libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; \ elif test -f ../../src/runtime/libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; then \ ${LN_S} ../../src/runtime/libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR} libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; \ fi - if test -f ../../src/runtime/objfwrt.dll; then \ - ${LN_S} ../../src/runtime/objfwrt.dll objfwrt.dll; \ + if test -f ../../src/runtime/objfwrt${OBJFWRT_LIB_MAJOR}.dll; then \ + ${LN_S} ../../src/runtime/objfwrt${OBJFWRT_LIB_MAJOR}.dll \ + objfwrt${OBJFWRT_LIB_MAJOR}.dll; \ fi if test -f ../../src/runtime/libobjfwrt.dylib; then \ ${LN_S} ../../src/runtime/libobjfwrt.dylib \ libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib; \ fi @@ -53,15 +56,17 @@ LD_LIBRARY_PATH=.$${LD_LIBRARY_PATH+:}$$LD_LIBRARY_PATH \ DYLD_LIBRARY_PATH=.$${DYLD_LIBRARY_PATH+:}$$DYLD_LIBRARY_PATH \ LIBRARY_PATH=.$${LIBRARY_PATH+:}$$LIBRARY_PATH \ ${WRAPPER} ./${PROG_NOINST}; EXIT=$$?; \ rm -f libobjfw.so.${OBJFW_LIB_MAJOR}; \ - rm -f objfw.so.${OBJFW_LIB_MAJOR_MINOR} objfw.dll; \ + rm -f libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; \ + rm -f objfw${OBJFW_LIB_MAJOR}.dll; \ rm -f libobjfw.${OBJFW_LIB_MAJOR}.dylib; \ rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR}; \ - rm -f objfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR} objfwrt.dll; \ + rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; \ + rm -f objfwrt${OBJFWRT_LIB_MAJOR}.dll; \ rm -f libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib; \ exit $$EXIT CPPFLAGS += -I../../src -I../../src/exceptions -I../../src/runtime -I../.. LIBS := -L../../src -lobjfw -L../../src/runtime ${RUNTIME_LIBS} ${LIBS} LD = ${OBJC} Index: utils/ofarc/LHAArchive.m ================================================================== --- utils/ofarc/LHAArchive.m +++ utils/ofarc/LHAArchive.m @@ -480,12 +480,17 @@ attributes.fileGroupOwnerAccountID]; entry.owner = attributes.fileOwnerAccountName; entry.group = attributes.fileGroupOwnerAccountName; #endif - if ([type isEqual: OFFileTypeDirectory]) + if ([type isEqual: OFFileTypeDirectory]) { entry.compressionMethod = @"-lhd-"; + + if (![entry.fileName hasSuffix: @"/"]) + entry.fileName = [entry.fileName + stringByAppendingString: @"/"]; + } output = [_archive streamForWritingEntry: entry]; if ([type isEqual: OFFileTypeRegular]) { unsigned long long written = 0; Index: utils/ofarc/OFArc.m ================================================================== --- utils/ofarc/OFArc.m +++ utils/ofarc/OFArc.m @@ -142,10 +142,31 @@ [OFStdErr writeLine: OF_LOCALIZED( @"writing_not_supported", @"Writing archives of type %[type] is not (yet) supported!", @"type", type)]; } + +static void +addFiles(id archive, OFArray OF_GENERIC(OFString *) *files) +{ + OFMutableArray *expandedFiles = + [OFMutableArray arrayWithCapacity: files.count]; + OFFileManager *fileManager = [OFFileManager defaultManager]; + + for (OFString *file in files) { + OFFileAttributes attributes = + [fileManager attributesOfItemAtPath: file]; + + if ([attributes.fileType isEqual: OFFileTypeDirectory]) + [expandedFiles addObjectsFromArray: + [fileManager subpathsOfDirectoryAtPath: file]]; + else + [expandedFiles addObject: file]; + } + + [archive addFiles: expandedFiles]; +} @implementation OFArc - (void)applicationDidFinishLaunching { OFString *outputDir, *encodingString, *type; @@ -334,11 +355,11 @@ openArchiveWithPath: remainingArguments.firstObject type: type mode: mode encoding: encoding]; - [archive addFiles: files]; + addFiles(archive, files); break; case 'l': if (remainingArguments.count != 1) help(OFStdErr, false, 1); Index: utils/ofhash/OFHash.m ================================================================== --- utils/ofhash/OFHash.m +++ utils/ofhash/OFHash.m @@ -41,12 +41,12 @@ static void help(void) { [OFStdErr writeLine: OF_LOCALIZED(@"usage", - @"Usage: %[prog] [--md5|--ripemd160|--sha1|--sha224|--sha256|" - @"--sha384|--sha512] file1 [file2 ...]", + @"Usage: %[prog] [--md5] [--ripemd160] [--sha1] [--sha224] " + @"[--sha256] [--sha384] [--sha512] file1 [file2 ...]", @"prog", [OFApplication programName])]; [OFApplication terminateWithStatus: 1]; } Index: utils/ofhash/lang/de.json ================================================================== --- utils/ofhash/lang/de.json +++ utils/ofhash/lang/de.json @@ -1,10 +1,10 @@ { "usage": [ - "Benutzung: %[prog] [--md5|--ripemd160|--sha1|--sha224|--sha256|", - "--sha384|--sha512] datei1 [datei2 ...]" + "Benutzung: %[prog] [--md5] [--ripemd160] [--sha1] [--sha224] ", + "[--sha256] [--sha384] [--sha512] datei1 [datei2 ...]" ], "unknown_long_option": "%[prog]: Unbekannte Option: --%[opt]", "unknown_option": "%[prog]: Unbekannte Option: -%[opt]", "failed_to_open_file": "Fehler beim Öffnen der Datei %[file]: %[error]", "failed_to_read_file": "Fehler beim Lesen der Datei %[file]: %[error]" } Index: utils/ofhttp/OFHTTP.m ================================================================== --- utils/ofhttp/OFHTTP.m +++ utils/ofhttp/OFHTTP.m @@ -530,11 +530,11 @@ #ifdef OF_HAVE_SANDBOX if (outputPath != nil) [sandbox unveilPath: outputPath permissions: (_continue ? @"rwc" : @"wc")]; else - [sandbox unveilPath: [[OFFileManger defaultManager] + [sandbox unveilPath: [[OFFileManager defaultManager] currentDirectoryPath] permissions: (_continue ? @"rwc" : @"wc")]; /* In case we use ObjOpenSSL for https later */ [sandbox unveilPath: @"/etc/ssl" permissions: @"r"];