diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/replicant/nx | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/replicant/nx')
64 files changed, 6115 insertions, 0 deletions
diff --git a/Src/replicant/nx/Android.mk b/Src/replicant/nx/Android.mk new file mode 100644 index 00000000..48d50f0d --- /dev/null +++ b/Src/replicant/nx/Android.mk @@ -0,0 +1,27 @@ +NX_LOCAL_PATH := $(call my-dir) +include $(NX_LOCAL_PATH)/cpufeatures/Android.mk + +LOCAL_PATH:= $(NX_LOCAL_PATH) + + +include $(CLEAR_VARS) +include $(ROOT_REPLICANT)/PlatformName.mk + +LOCAL_MODULE := nx +LOCAL_MODULE_FILENAME := libnx.$(PLATFORM_NAME) +LOCAL_C_INCLUDES := $(LOCAL_PATH)/.. +LOCAL_CFLAGS := -fvisibility=hidden +LOCAL_SRC_FILES := android/nxcondition.c android/nxstring.c android/nxuri.c android/nxmutablestring.c android/nxdata.c android/nxsemaphore.c android/nxthread.c android/nxfile.c android/nxlog.c android/NXFileObject.cpp android/NXFileProgressiveDownloader.cpp android/nxonce.c +LOCAL_SRC_FILES += linux/nxsleep.c linux/nxpath.c +LOCAL_SRC_FILES += cpufeatures/cpu-features.c + +ifeq ($(TARGET_ARCH_ABI),armeabi-v7a) +LOCAL_SRC_FILES += android-armv7/nxonce-armv6.S +else +LOCAL_SRC_FILES += android-armv5/nxonce-armv5.S +endif + +LOCAL_STATIC_LIBRARIES := nu foundation +LOCAL_SHARED_LIBRARIES := nu foundation jnet +LOCAL_LDFLAGS := -llog +include $(BUILD_SHARED_LIBRARY) diff --git a/Src/replicant/nx/Makefile b/Src/replicant/nx/Makefile new file mode 100644 index 00000000..4bdea3fb --- /dev/null +++ b/Src/replicant/nx/Makefile @@ -0,0 +1,89 @@ +# ex: set ts=8 noet: + +MODULE_NAME := nx + +OS := $(shell sh -c 'uname -s 2>/dev/null || echo not') + +ifeq ($(OS),Linux) +DIR := linux +DIRARCH := linux +else ifeq ($(OS),Darwin) +DIR := osx +DIRARCH := osx-amd64 +else +$(error OS unrecognized ($OS)) +endif + +CSOURCES := $(DIR)/nxstring.c $(DIR)/nxuri.c $(DIR)/nxdata.c $(DIR)/nxsemaphore.c $(DIRARCH)/nxonce.c $(DIR)/nxpath.c $(DIR)/nxcondition.c $(DIR)/nxthread.c $(DIR)/nxfile.c $(DIR)/nxsleep.c +CPPSOURCES := $(DIR)/NXFileObject.cpp $(DIR)/NXFileProgressiveDownloader.cpp + +LIBRARY_FILENAME := lib$(MODULE_NAME).so +OUTPUT_PATH := ../build/$(MODULE_NAME) +ARCHIVE_PATH := ../build/lib +LIBRARY_FILEPATH := ../build/lib/$(LIBRARY_FILENAME) + +CPPOBJS := $(patsubst %.cpp,$(OUTPUT_PATH)/%.o,$(CPPSOURCES)) +CPPDEPS := $(patsubst %.o,$(OUTPUT_PATH)/%.d,$(CPPOBJS)) +COBJS := $(patsubst %.c,$(OUTPUT_PATH)/%.o,$(CSOURCES)) +CDEPS := $(patsubst %.o,$(OUTPUT_PATH)/%.d,$(COBJS)) + +OBJS := $(CPPOBJS) $(COBJS) +DEPS := $(CPPDEPS) $(CDEPS) + +CFLAGS= -I.. -DREPLICANT_NO_ICY -DREPLICANT_NO_ULTRAVOX -DREPLICANT_NO_HTTP -D_LARGEFILE64_SOURCE -fPIC #-fvisibility=hidden +CPPFLAGS := ${CFLAGS} +CFLAGS += -std=gnu99 # C but not CPP, sneaky + +LDFLAGS =-lc -lpthread -lz #-fvisibility=hidden + +ifeq ($(OS),Linux) +LDFLAGS += -lrt +endif + +ifeq ($(OS),Darwin) +CFLAGS += -F /System/Library/Frameworks/CoreServices.framework/Frameworks +LDFLAGS += -framework CoreFoundation -framework CoreServices +endif + +build: build-dir $(LIBRARY_FILEPATH) + +build-dir: + @mkdir -p $(OUTPUT_PATH)/$(DIR) > /dev/null 2> /dev/null + @mkdir -p $(OUTPUT_PATH)/$(DIRARCH) > /dev/null 2> /dev/null + @mkdir -p $(OUTPUT_PATH) > /dev/null 2> /dev/null + @mkdir -p $(ARCHIVE_PATH) > /dev/null 2> /dev/null + +dep: + @rm ${DEPS} + +$(OUTPUT_PATH)/%.o: %.cpp + #@echo Compiling $*.cpp + @$(CXX) $(CPPFLAGS) -MMD -MF $(OUTPUT_PATH)/$*.d -MT $(OUTPUT_PATH)/$*.o -c $*.cpp -o $(OUTPUT_PATH)/$*.o + +$(OUTPUT_PATH)/$(DIR)/%.o: %.cpp + #@echo Compiling $*.cpp + @$(CXX) $(CPPFLAGS) -MMD -MF $(OUTPUT_PATH)/$(DIR)/$*.d -MT $(OUTPUT_PATH)/$(DIR)/$*.o -c $*.cpp -o $(OUTPUT_PATH)/$(DIR)/$*.o + +$(OUTPUT_PATH)/%.o: %.c + #@echo Compiling $*.c + @$(CC) $(CFLAGS) -MMD -MF $(OUTPUT_PATH)/$*.d -MT $(OUTPUT_PATH)/$*.o -c $*.c -o $(OUTPUT_PATH)/$*.o + +$(OUTPUT_PATH)/.*/%.o: %.c + #@echo Compiling $*.c + @$(CC) $(CFLAGS) -MMD -MF $(OUTPUT_PATH)/$*.d -MT $(OUTPUT_PATH)/$*.o -c $*.c -o $(OUTPUT_PATH)/$(DIR)/$*.o + +ifeq ($(OS),Darwin) +LIBLDFLAGS = -Wl,-install_name,libnx.so +else +LIBLDFLAGS = -Wl,-soname,libnx.so +endif + +$(LIBRARY_FILEPATH): ${OBJS} + $(MAKE) -C ../nu + $(MAKE) -C ../jnetlib + @$(CXX) -Wl,-L,'../build/lib' -shared $(LIBLDFLAGS) -o $(LIBRARY_FILEPATH) ${OBJS} ${LDFLAGS} -lnu -ljnet + +clean: + -rm -f ${OBJS} $(LIBRARY_FILENAME) ${DEPS} + +-include $(DEPS) diff --git a/Src/replicant/nx/VERSION b/Src/replicant/nx/VERSION new file mode 100644 index 00000000..b966e81a --- /dev/null +++ b/Src/replicant/nx/VERSION @@ -0,0 +1 @@ +1.2.4
\ No newline at end of file diff --git a/Src/replicant/nx/cpufeatures/Android.mk b/Src/replicant/nx/cpufeatures/Android.mk new file mode 100644 index 00000000..ec988ba3 --- /dev/null +++ b/Src/replicant/nx/cpufeatures/Android.mk @@ -0,0 +1,7 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE := nullsoft-cpufeatures +LOCAL_SRC_FILES := cpu-features.c +LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) +include $(BUILD_STATIC_LIBRARY) diff --git a/Src/replicant/nx/cpufeatures/cpu-features.c b/Src/replicant/nx/cpufeatures/cpu-features.c new file mode 100644 index 00000000..488833c5 --- /dev/null +++ b/Src/replicant/nx/cpufeatures/cpu-features.c @@ -0,0 +1,432 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* ChangeLog for this library: + * + * NDK r5: Handle buggy kernels which report a CPU Architecture number of 7 + * for an ARMv6 CPU (see below). + * + * Handle kernels that only report 'neon', and not 'vfpv3' + * (VFPv3 is mandated by the ARM architecture is Neon is implemented) + * + * Handle kernels that only report 'vfpv3d16', and not 'vfpv3' + * + * Fix x86 compilation. Report ANDROID_CPU_FAMILY_X86 in + * android_getCpuFamily(). + * + * NDK r4: Initial release + */ +#include <sys/system_properties.h> +#ifdef __arm__ +#include <machine/cpu-features.h> +#endif +#include <pthread.h> +#include "cpu-features.h" +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <errno.h> + +static pthread_once_t g_once; +static AndroidCpuFamily g_cpuFamily; +static uint64_t g_cpuFeatures; +static int g_cpuCount; + +static const int android_cpufeatures_debug = 0; + +#ifdef __arm__ +# define DEFAULT_CPU_FAMILY ANDROID_CPU_FAMILY_ARM +#elif defined __i386__ +# define DEFAULT_CPU_FAMILY ANDROID_CPU_FAMILY_X86 +#else +# define DEFAULT_CPU_FAMILY ANDROID_CPU_FAMILY_UNKNOWN +#endif + +#define D(...) \ + do { \ + if (android_cpufeatures_debug) { \ + printf(__VA_ARGS__); fflush(stdout); \ + } \ + } while (0) + +#ifdef __i386__ +static __inline__ void x86_cpuid(int func, int values[4]) +{ + int a, b, c, d; + /* We need to preserve ebx since we're compiling PIC code */ + /* this means we can't use "=b" for the second output register */ + __asm__ __volatile__ ( \ + "push %%ebx\n" + "cpuid\n" \ + "mov %1, %%ebx\n" + "pop %%ebx\n" + : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \ + : "a" (func) \ + ); + values[0] = a; + values[1] = b; + values[2] = c; + values[3] = d; +} +#endif + +/* Read the content of /proc/cpuinfo into a user-provided buffer. + * Return the length of the data, or -1 on error. Does *not* + * zero-terminate the content. Will not read more + * than 'buffsize' bytes. + */ +static int +read_file(const char* pathname, char* buffer, size_t buffsize) +{ + int fd, len; + + fd = open(pathname, O_RDONLY); + if (fd < 0) + return -1; + + do { + len = read(fd, buffer, buffsize); + } while (len < 0 && errno == EINTR); + + close(fd); + + return len; +} + +/* Extract the content of a the first occurence of a given field in + * the content of /proc/cpuinfo and return it as a heap-allocated + * string that must be freed by the caller. + * + * Return NULL if not found + */ +static char* +extract_cpuinfo_field(char* buffer, int buflen, const char* field) +{ + int fieldlen = strlen(field); + char* bufend = buffer + buflen; + char* result = NULL; + int len, ignore; + const char *p, *q; + + /* Look for first field occurence, and ensures it starts the line. + */ + p = buffer; + bufend = buffer + buflen; + for (;;) { + p = memmem(p, bufend-p, field, fieldlen); + if (p == NULL) + goto EXIT; + + if (p == buffer || p[-1] == '\n') + break; + + p += fieldlen; + } + + /* Skip to the first column followed by a space */ + p += fieldlen; + p = memchr(p, ':', bufend-p); + if (p == NULL || p[1] != ' ') + goto EXIT; + + /* Find the end of the line */ + p += 2; + q = memchr(p, '\n', bufend-p); + if (q == NULL) + q = bufend; + + /* Copy the line into a heap-allocated buffer */ + len = q-p; + result = malloc(len+1); + if (result == NULL) + goto EXIT; + + memcpy(result, p, len); + result[len] = '\0'; + +EXIT: + return result; +} + +/* Count the number of occurences of a given field prefix in /proc/cpuinfo. + */ +static int +count_cpuinfo_field(char* buffer, int buflen, const char* field) +{ + int fieldlen = strlen(field); + const char* p = buffer; + const char* bufend = buffer + buflen; + const char* q; + int count = 0; + + for (;;) { + const char* q; + + p = memmem(p, bufend-p, field, fieldlen); + if (p == NULL) + break; + + /* Ensure that the field is at the start of a line */ + if (p > buffer && p[-1] != '\n') { + p += fieldlen; + continue; + } + + + /* skip any whitespace */ + q = p + fieldlen; + while (q < bufend && (*q == ' ' || *q == '\t')) + q++; + + /* we must have a colon now */ + if (q < bufend && *q == ':') { + count += 1; + q ++; + } + p = q; + } + + return count; +} + +/* Like strlen(), but for constant string literals */ +#define STRLEN_CONST(x) ((sizeof(x)-1) + + +/* Checks that a space-separated list of items contains one given 'item'. + * Returns 1 if found, 0 otherwise. + */ +static int +has_list_item(const char* list, const char* item) +{ + const char* p = list; + int itemlen = strlen(item); + + if (list == NULL) + return 0; + + while (*p) { + const char* q; + + /* skip spaces */ + while (*p == ' ' || *p == '\t') + p++; + + /* find end of current list item */ + q = p; + while (*q && *q != ' ' && *q != '\t') + q++; + + if (itemlen == q-p && !memcmp(p, item, itemlen)) + return 1; + + /* skip to next item */ + p = q; + } + return 0; +} + + +static void +android_cpuInit(void) +{ + char cpuinfo[4096]; + int cpuinfo_len; + + g_cpuFamily = DEFAULT_CPU_FAMILY; + g_cpuFeatures = 0; + g_cpuCount = 1; + + cpuinfo_len = read_file("/proc/cpuinfo", cpuinfo, sizeof cpuinfo); + D("cpuinfo_len is (%d):\n%.*s\n", cpuinfo_len, + cpuinfo_len >= 0 ? cpuinfo_len : 0, cpuinfo); + + if (cpuinfo_len < 0) /* should not happen */ { + return; + } + + /* Count the CPU cores, the value may be 0 for single-core CPUs */ + g_cpuCount = count_cpuinfo_field(cpuinfo, cpuinfo_len, "processor"); + if (g_cpuCount == 0) { + g_cpuCount = count_cpuinfo_field(cpuinfo, cpuinfo_len, "Processor"); + if (g_cpuCount == 0) { + g_cpuCount = 1; + } + } + + D("found cpuCount = %d\n", g_cpuCount); + +#ifdef __ARM_ARCH__ + { + char* features = NULL; + char* architecture = NULL; + + /* Extract architecture from the "CPU Architecture" field. + * The list is well-known, unlike the the output of + * the 'Processor' field which can vary greatly. + * + * See the definition of the 'proc_arch' array in + * $KERNEL/arch/arm/kernel/setup.c and the 'c_show' function in + * same file. + */ + char* cpuArch = extract_cpuinfo_field(cpuinfo, cpuinfo_len, "CPU architecture"); + + if (cpuArch != NULL) { + char* end; + long archNumber; + int hasARMv7 = 0; + + D("found cpuArch = '%s'\n", cpuArch); + + /* read the initial decimal number, ignore the rest */ + archNumber = strtol(cpuArch, &end, 10); + + /* Here we assume that ARMv8 will be upwards compatible with v7 + * in the future. Unfortunately, there is no 'Features' field to + * indicate that Thumb-2 is supported. + */ + if (end > cpuArch && archNumber >= 7) { + hasARMv7 = 1; + } + + /* Unfortunately, it seems that certain ARMv6-based CPUs + * report an incorrect architecture number of 7! + * + * See http://code.google.com/p/android/issues/detail?id=10812 + * + * We try to correct this by looking at the 'elf_format' + * field reported by the 'Processor' field, which is of the + * form of "(v7l)" for an ARMv7-based CPU, and "(v6l)" for + * an ARMv6-one. + */ + if (hasARMv7) { + char* cpuProc = extract_cpuinfo_field(cpuinfo, cpuinfo_len, + "Processor"); + if (cpuProc != NULL) { + D("found cpuProc = '%s'\n", cpuProc); + if (has_list_item(cpuProc, "(v6l)")) { + D("CPU processor and architecture mismatch!!\n"); + hasARMv7 = 0; + } + free(cpuProc); + } + } + + if (hasARMv7) { + g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_ARMv7; + } + + /* The LDREX / STREX instructions are available from ARMv6 */ + if (archNumber >= 6) { + g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_LDREX_STREX; + } + + free(cpuArch); + } + + /* Extract the list of CPU features from 'Features' field */ + char* cpuFeatures = extract_cpuinfo_field(cpuinfo, cpuinfo_len, "Features"); + + if (cpuFeatures != NULL) { + + D("found cpuFeatures = '%s'\n", cpuFeatures); + + if (has_list_item(cpuFeatures, "vfp")) + g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFP; + + if (has_list_item(cpuFeatures, "vfpv3")) + g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3; + + else if (has_list_item(cpuFeatures, "vfpv3d16")) + g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3; + + if (has_list_item(cpuFeatures, "neon")) { + /* Note: Certain kernels only report neon but not vfpv3 + * in their features list. However, ARM mandates + * that if Neon is implemented, so must be VFPv3 + * so always set the flag. + */ + g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_NEON | + ANDROID_CPU_ARM_FEATURE_VFPv3; + } + free(cpuFeatures); + } + } +#endif /* __ARM_ARCH__ */ + +#ifdef __i386__ + g_cpuFamily = ANDROID_CPU_FAMILY_X86; + + int regs[4]; + +/* According to http://en.wikipedia.org/wiki/CPUID */ +#define VENDOR_INTEL_b 0x756e6547 +#define VENDOR_INTEL_c 0x6c65746e +#define VENDOR_INTEL_d 0x49656e69 + + x86_cpuid(0, regs); + int vendorIsIntel = (regs[1] == VENDOR_INTEL_b && + regs[2] == VENDOR_INTEL_c && + regs[3] == VENDOR_INTEL_d); + + x86_cpuid(1, regs); + if ((regs[2] & (1 << 9)) != 0) { + g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SSSE3; + } + if ((regs[2] & (1 << 23)) != 0) { + g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_POPCNT; + } + if (vendorIsIntel && (regs[2] & (1 << 22)) != 0) { + g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_MOVBE; + } +#endif +} + + +AndroidCpuFamily +android_getCpuFamily(void) +{ + pthread_once(&g_once, android_cpuInit); + return g_cpuFamily; +} + + +uint64_t +android_getCpuFeatures(void) +{ + pthread_once(&g_once, android_cpuInit); + return g_cpuFeatures; +} + + +int +android_getCpuCount(void) +{ + pthread_once(&g_once, android_cpuInit); + return g_cpuCount; +} diff --git a/Src/replicant/nx/cpufeatures/cpu-features.h b/Src/replicant/nx/cpufeatures/cpu-features.h new file mode 100644 index 00000000..ef724174 --- /dev/null +++ b/Src/replicant/nx/cpufeatures/cpu-features.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef CPU_FEATURES_H +#define CPU_FEATURES_H + +#include <sys/cdefs.h> +#include <stdint.h> + +__BEGIN_DECLS + +typedef enum { + ANDROID_CPU_FAMILY_UNKNOWN = 0, + ANDROID_CPU_FAMILY_ARM, + ANDROID_CPU_FAMILY_X86, + + ANDROID_CPU_FAMILY_MAX /* do not remove */ + +} AndroidCpuFamily; + +/* Return family of the device's CPU */ +__attribute__ ((visibility("default"))) extern AndroidCpuFamily android_getCpuFamily(void); + +enum { + ANDROID_CPU_ARM_FEATURE_ARMv7 = (1 << 0), + ANDROID_CPU_ARM_FEATURE_VFPv3 = (1 << 1), + ANDROID_CPU_ARM_FEATURE_NEON = (1 << 2), + ANDROID_CPU_ARM_FEATURE_LDREX_STREX = (1 << 3), + ANDROID_CPU_ARM_FEATURE_ARMv6=ANDROID_CPU_ARM_FEATURE_LDREX_STREX, + ANDROID_CPU_ARM_FEATURE_VFP = (1 << 4), +}; + +enum { + ANDROID_CPU_X86_FEATURE_SSSE3 = (1 << 0), + ANDROID_CPU_X86_FEATURE_POPCNT = (1 << 1), + ANDROID_CPU_X86_FEATURE_MOVBE = (1 << 2), +}; + +__attribute__ ((visibility("default"))) extern uint64_t android_getCpuFeatures(void); + +/* Return the number of CPU cores detected on this device. */ +__attribute__ ((visibility("default"))) extern int android_getCpuCount(void); + +__END_DECLS + +#endif /* CPU_FEATURES_H */ diff --git a/Src/replicant/nx/nx.h b/Src/replicant/nx/nx.h new file mode 100644 index 00000000..19bf6efe --- /dev/null +++ b/Src/replicant/nx/nx.h @@ -0,0 +1,14 @@ +#pragma once +#include "nx/nxapi.h" +#include "nx/nxcondition.h" +#include "nx/nxdata.h" +#include "nx/nxfile.h" +#include "nx/nxmutablestring.h" +#include "nx/nxonce.h" +#include "nx/nxpath.h" +#include "nx/nxsemaphore.h" +#include "nx/nxsleep.h" +#include "nx/nxstring.h" +#include "nx/nxthread.h" +#include "nx/nxuri.h" +#include "nx/nxtime.h" diff --git a/Src/replicant/nx/nx.rc b/Src/replicant/nx/nx.rc new file mode 100644 index 00000000..fcff7711 --- /dev/null +++ b/Src/replicant/nx/nx.rc @@ -0,0 +1,76 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// English (U.K.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "#include ""version.rc2""\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.K.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#include "version.rc2" + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/Src/replicant/nx/nx.sln b/Src/replicant/nx/nx.sln new file mode 100644 index 00000000..233d259e --- /dev/null +++ b/Src/replicant/nx/nx.sln @@ -0,0 +1,67 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29509.3 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nx", "nx.vcxproj", "{2851CF33-337D-44D9-BA6D-30547B1CDEF0}" + ProjectSection(ProjectDependencies) = postProject + {0F9730E4-45DA-4BD2-A50A-403A4BC9751A} = {0F9730E4-45DA-4BD2-A50A-403A4BC9751A} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nu", "..\nu\nu.vcxproj", "{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jnetlib", "..\jnetlib\jnetlib.vcxproj", "{E105A0A2-7391-47C5-86AC-718003524C3D}" + ProjectSection(ProjectDependencies) = postProject + {0F9730E4-45DA-4BD2-A50A-403A4BC9751A} = {0F9730E4-45DA-4BD2-A50A-403A4BC9751A} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "..\zlib\zlib.vcxproj", "{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2851CF33-337D-44D9-BA6D-30547B1CDEF0}.Debug|Win32.ActiveCfg = Debug|Win32 + {2851CF33-337D-44D9-BA6D-30547B1CDEF0}.Debug|Win32.Build.0 = Debug|Win32 + {2851CF33-337D-44D9-BA6D-30547B1CDEF0}.Debug|x64.ActiveCfg = Debug|x64 + {2851CF33-337D-44D9-BA6D-30547B1CDEF0}.Debug|x64.Build.0 = Debug|x64 + {2851CF33-337D-44D9-BA6D-30547B1CDEF0}.Release|Win32.ActiveCfg = Release|Win32 + {2851CF33-337D-44D9-BA6D-30547B1CDEF0}.Release|Win32.Build.0 = Release|Win32 + {2851CF33-337D-44D9-BA6D-30547B1CDEF0}.Release|x64.ActiveCfg = Release|x64 + {2851CF33-337D-44D9-BA6D-30547B1CDEF0}.Release|x64.Build.0 = Release|x64 + {F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Debug|Win32.ActiveCfg = Debug|Win32 + {F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Debug|Win32.Build.0 = Debug|Win32 + {F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Debug|x64.ActiveCfg = Debug|x64 + {F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Debug|x64.Build.0 = Debug|x64 + {F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Release|Win32.ActiveCfg = Release|Win32 + {F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Release|Win32.Build.0 = Release|Win32 + {F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Release|x64.ActiveCfg = Release|x64 + {F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Release|x64.Build.0 = Release|x64 + {E105A0A2-7391-47C5-86AC-718003524C3D}.Debug|Win32.ActiveCfg = Debug|Win32 + {E105A0A2-7391-47C5-86AC-718003524C3D}.Debug|Win32.Build.0 = Debug|Win32 + {E105A0A2-7391-47C5-86AC-718003524C3D}.Debug|x64.ActiveCfg = Debug|x64 + {E105A0A2-7391-47C5-86AC-718003524C3D}.Debug|x64.Build.0 = Debug|x64 + {E105A0A2-7391-47C5-86AC-718003524C3D}.Release|Win32.ActiveCfg = Release|Win32 + {E105A0A2-7391-47C5-86AC-718003524C3D}.Release|Win32.Build.0 = Release|Win32 + {E105A0A2-7391-47C5-86AC-718003524C3D}.Release|x64.ActiveCfg = Release|x64 + {E105A0A2-7391-47C5-86AC-718003524C3D}.Release|x64.Build.0 = Release|x64 + {0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Debug|Win32.ActiveCfg = Debug|Win32 + {0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Debug|Win32.Build.0 = Debug|Win32 + {0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Debug|x64.ActiveCfg = Debug|x64 + {0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Debug|x64.Build.0 = Debug|x64 + {0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Release|Win32.ActiveCfg = Release|Win32 + {0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Release|Win32.Build.0 = Release|Win32 + {0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Release|x64.ActiveCfg = Release|x64 + {0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {C4E799C1-027B-487B-8E1A-31F2D26A1AFE} + EndGlobalSection +EndGlobal diff --git a/Src/replicant/nx/nx.vcxproj b/Src/replicant/nx/nx.vcxproj new file mode 100644 index 00000000..2dc85a2d --- /dev/null +++ b/Src/replicant/nx/nx.vcxproj @@ -0,0 +1,290 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{57C90706-B25D-4ACA-9B33-95CDB2427C27}</ProjectGuid> + <RootNamespace>nx</RootNamespace> + <WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <LinkIncremental>false</LinkIncremental> + <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir> + <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir> + <TargetName>nxlite</TargetName> + <IncludePath>$(IncludePath)</IncludePath> + <LibraryPath>$(LibraryPath)</LibraryPath> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <LinkIncremental>false</LinkIncremental> + <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir> + <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir> + <TargetName>nxlite</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <LinkIncremental>false</LinkIncremental> + <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir> + <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir> + <TargetName>nxlite</TargetName> + <IncludePath>$(IncludePath)</IncludePath> + <LibraryPath>$(LibraryPath)</LibraryPath> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <LinkIncremental>false</LinkIncremental> + <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir> + <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir> + <TargetName>nxlite</TargetName> + </PropertyGroup> + <PropertyGroup Label="Vcpkg"> + <VcpkgEnableManifest>false</VcpkgEnableManifest> + </PropertyGroup> + <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <VcpkgInstalledDir> + </VcpkgInstalledDir> + <VcpkgUseStatic>false</VcpkgUseStatic> + <VcpkgConfiguration>Debug</VcpkgConfiguration> + <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet> + </PropertyGroup> + <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <VcpkgInstalledDir> + </VcpkgInstalledDir> + <VcpkgUseStatic>false</VcpkgUseStatic> + <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet> + </PropertyGroup> + <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <VcpkgInstalledDir> + </VcpkgInstalledDir> + <VcpkgUseStatic>false</VcpkgUseStatic> + <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet> + <VcpkgConfiguration>Debug</VcpkgConfiguration> + </PropertyGroup> + <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <VcpkgInstalledDir> + </VcpkgInstalledDir> + <VcpkgUseStatic>false</VcpkgUseStatic> + <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <Optimization>Disabled</Optimization> + <AdditionalIncludeDirectories>..;../Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;NX_EXPORTS;_WIN32_WINNT=0x601;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <MinimalRebuild>false</MinimalRebuild> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <WarningLevel>Level3</WarningLevel> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <DisableSpecificWarnings>4996;6011;6031;%(DisableSpecificWarnings)</DisableSpecificWarnings> + <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> + </ClCompile> + <Link> + <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> + <DelayLoadDLLs>jnetlib.dll;%(DelayLoadDLLs)</DelayLoadDLLs> + <GenerateDebugInformation>true</GenerateDebugInformation> + <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile> + <SubSystem>Windows</SubSystem> + <ImportLibrary>$(ProjectDir)x86_Debug\$(ProjectName).lib</ImportLibrary> + <TargetMachine>MachineX86</TargetMachine> + <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers> + <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies> + <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + </Link> + <PostBuildEvent> + <Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\ +xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\ </Command> + <Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\'</Message> + </PostBuildEvent> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <Optimization>Disabled</Optimization> + <AdditionalIncludeDirectories>..;../Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN64;_DEBUG;_WINDOWS;_USRDLL;NX_EXPORTS;_WIN32_WINNT=0x601;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <MinimalRebuild>false</MinimalRebuild> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <WarningLevel>Level3</WarningLevel> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <DisableSpecificWarnings>4996;6011;6031;%(DisableSpecificWarnings)</DisableSpecificWarnings> + <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> + </ClCompile> + <Link> + <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> + <DelayLoadDLLs>jnetlib.dll;%(DelayLoadDLLs)</DelayLoadDLLs> + <GenerateDebugInformation>true</GenerateDebugInformation> + <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile> + <SubSystem>Windows</SubSystem> + <ImportLibrary>$(ProjectDir)x64_Debug\$(ProjectName).lib</ImportLibrary> + <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers> + <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies> + </Link> + <PostBuildEvent> + <Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\ +xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\ </Command> + <Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\'</Message> + </PostBuildEvent> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <Optimization>MinSpace</Optimization> + <IntrinsicFunctions>true</IntrinsicFunctions> + <FavorSizeOrSpeed>Size</FavorSizeOrSpeed> + <AdditionalIncludeDirectories>..;../Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;NX_EXPORTS;_WIN32_WINNT=0x601;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + <BufferSecurityCheck>false</BufferSecurityCheck> + <WarningLevel>Level3</WarningLevel> + <DebugInformationFormat>None</DebugInformationFormat> + <DisableSpecificWarnings>4996;4244;4355;6011;6031;%(DisableSpecificWarnings)</DisableSpecificWarnings> + <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> + </ClCompile> + <Link> + <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> + <DelayLoadDLLs>jnetlib.dll;%(DelayLoadDLLs)</DelayLoadDLLs> + <GenerateDebugInformation>false</GenerateDebugInformation> + <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile> + <SubSystem>Windows</SubSystem> + <OptimizeReferences>true</OptimizeReferences> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <ImportLibrary>$(ProjectDir)x86_Release\$(ProjectName).lib</ImportLibrary> + <TargetMachine>MachineX86</TargetMachine> + <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers> + <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies> + </Link> + <PostBuildEvent> + <Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\ </Command> + <Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\'</Message> + </PostBuildEvent> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <Optimization>MinSpace</Optimization> + <IntrinsicFunctions>true</IntrinsicFunctions> + <FavorSizeOrSpeed>Size</FavorSizeOrSpeed> + <AdditionalIncludeDirectories>..;../Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_USRDLL;NX_EXPORTS;_WIN32_WINNT=0x601;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + <BufferSecurityCheck>false</BufferSecurityCheck> + <WarningLevel>Level3</WarningLevel> + <DebugInformationFormat>None</DebugInformationFormat> + <DisableSpecificWarnings>4996;4244;4355;6011;6031;%(DisableSpecificWarnings)</DisableSpecificWarnings> + <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> + </ClCompile> + <Link> + <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> + <DelayLoadDLLs>jnetlib.dll;%(DelayLoadDLLs)</DelayLoadDLLs> + <GenerateDebugInformation>false</GenerateDebugInformation> + <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile> + <SubSystem>Windows</SubSystem> + <OptimizeReferences>true</OptimizeReferences> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <ImportLibrary>$(ProjectDir)x64_Release\$(ProjectName).lib</ImportLibrary> + <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers> + <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies> + </Link> + <PostBuildEvent> + <Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\ </Command> + <Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\'</Message> + </PostBuildEvent> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="win\nxdata.c" /> + <ClCompile Include="win\nxfile.c" /> + <ClCompile Include="win\NXFileObject.cpp" /> + <ClCompile Include="win\NXFileProgressiveDownloader.cpp" /> + <ClCompile Include="win\nxonce.c" /> + <ClCompile Include="win\nxpath.c" /> + <ClCompile Include="win\nxsleep.c" /> + <ClCompile Include="win\nxstring.c" /> + <ClCompile Include="win\nxthread.c" /> + <ClCompile Include="win\nxuri.c" /> + <ClCompile Include="win\NXZipFile.cpp" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\foundation\error.h" /> + <ClInclude Include="..\foundation\guid.h" /> + <ClInclude Include="..\foundation\types.h" /> + <ClInclude Include="nxapi.h" /> + <ClInclude Include="nxstring.h" /> + <ClInclude Include="nxuri.h" /> + <ClInclude Include="resource.h" /> + <ClInclude Include="win\nxonce.h" /> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="nx.rc" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\Wasabi\Wasabi.vcxproj"> + <Project>{3e0bfa8a-b86a-42e9-a33f-ec294f823f7f}</Project> + </ProjectReference> + <ProjectReference Include="..\..\WAT\WAT.vcxproj"> + <Project>{c5714908-a71f-4644-bd95-aad8ee7914da}</Project> + </ProjectReference> + <ProjectReference Include="..\jnetlib\jnetlib.vcxproj"> + <Project>{e105a0a2-7391-47c5-86ac-718003524c3d}</Project> + </ProjectReference> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project>
\ No newline at end of file diff --git a/Src/replicant/nx/nx.vcxproj.filters b/Src/replicant/nx/nx.vcxproj.filters new file mode 100644 index 00000000..e2e495eb --- /dev/null +++ b/Src/replicant/nx/nx.vcxproj.filters @@ -0,0 +1,80 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <ClCompile Include="win\nxdata.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="win\nxfile.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="win\NXFileObject.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="win\NXFileProgressiveDownloader.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="win\nxonce.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="win\nxpath.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="win\nxsleep.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="win\nxstring.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="win\nxthread.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="win\nxuri.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="win\NXZipFile.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\foundation\error.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\foundation\guid.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="win\nxonce.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="resource.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\foundation\types.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="nxstring.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="nxuri.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="nxapi.h"> + <Filter>Header Files</Filter> + </ClInclude> + </ItemGroup> + <ItemGroup> + <Filter Include="Header Files"> + <UniqueIdentifier>{e3ece7c2-5453-4ab4-9b86-9c6e0ea664d9}</UniqueIdentifier> + </Filter> + <Filter Include="Ressource Files"> + <UniqueIdentifier>{fe5588c0-7153-48f2-b1ba-c2406e319412}</UniqueIdentifier> + </Filter> + <Filter Include="Source Files"> + <UniqueIdentifier>{44167388-5010-436c-8849-1fc629ca5549}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="nx.rc"> + <Filter>Ressource Files</Filter> + </ResourceCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/Src/replicant/nx/nx.xcodeproj/project.pbxproj b/Src/replicant/nx/nx.xcodeproj/project.pbxproj new file mode 100644 index 00000000..3c80eb9d --- /dev/null +++ b/Src/replicant/nx/nx.xcodeproj/project.pbxproj @@ -0,0 +1,802 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXAggregateTarget section */ + 00B73401151BADB700A8251C /* nx-prepare */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 00B73402151BADB700A8251C /* Build configuration list for PBXAggregateTarget "nx-prepare" */; + buildPhases = ( + 00B73405151BADCC00A8251C /* Generate Version Info */, + ); + dependencies = ( + 0039B369152A1F3500D96D3E /* PBXTargetDependency */, + ); + name = "nx-prepare"; + productName = "nx-version"; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 00512B97156BD61500115B09 /* nxtime.h in Headers */ = {isa = PBXBuildFile; fileRef = 00512B96156BD61500115B09 /* nxtime.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 00512B9A156BD62800115B09 /* nxtime.h in Headers */ = {isa = PBXBuildFile; fileRef = 00512B99156BD62800115B09 /* nxtime.h */; }; + 00512B9B156BD66500115B09 /* nxtime.h in Copy Mac OS X Public Headers */ = {isa = PBXBuildFile; fileRef = 00512B99156BD62800115B09 /* nxtime.h */; }; + 0062CA5B170B228300CBFD15 /* MessageLoop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0062CA59170B228300CBFD15 /* MessageLoop.cpp */; }; + 0062CA5C170B228300CBFD15 /* MessageLoop.h in Headers */ = {isa = PBXBuildFile; fileRef = 0062CA5A170B228300CBFD15 /* MessageLoop.h */; }; + 00695D1816E70C1A009CB115 /* NXFileProgressiveDownloader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00695D1516E70C1A009CB115 /* NXFileProgressiveDownloader.cpp */; }; + 00695D1916E70C1A009CB115 /* nxlog.c in Sources */ = {isa = PBXBuildFile; fileRef = 00695D1616E70C1A009CB115 /* nxlog.c */; }; + 00695D1A16E70C1A009CB115 /* nxlog.h in Headers */ = {isa = PBXBuildFile; fileRef = 00695D1716E70C1A009CB115 /* nxlog.h */; }; + 00695D1E16E70D19009CB115 /* nxlog.h in Headers */ = {isa = PBXBuildFile; fileRef = 00695D1D16E70D19009CB115 /* nxlog.h */; }; + 00695D2016E70D2B009CB115 /* NXFileObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 00695D1F16E70D2B009CB115 /* NXFileObject.h */; }; + 00695D2E16E7DEB5009CB115 /* libjnetlib-1.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 00695D2D16E7DEB5009CB115 /* libjnetlib-1.dylib */; }; + 00695D4316E86E28009CB115 /* nxlog.h in Copy Mac OS X Public Headers */ = {isa = PBXBuildFile; fileRef = 00695D1716E70C1A009CB115 /* nxlog.h */; }; + 00723DD5150E8CCD006847F2 /* nxfile.c in Sources */ = {isa = PBXBuildFile; fileRef = 00723DD3150E8CCD006847F2 /* nxfile.c */; }; + 00723DD6150E8CCD006847F2 /* nxfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 00723DD4150E8CCD006847F2 /* nxfile.h */; }; + 00723DD8150E8CF0006847F2 /* nxfile.h in Copy Mac OS X Public Headers */ = {isa = PBXBuildFile; fileRef = 00723DD4150E8CCD006847F2 /* nxfile.h */; }; + 00723DDA150E8D86006847F2 /* nxsleep.h in Headers */ = {isa = PBXBuildFile; fileRef = 00723DD9150E8D86006847F2 /* nxsleep.h */; }; + 00723DDB150E8D9C006847F2 /* nxsleep.h in Copy Mac OS X Public Headers */ = {isa = PBXBuildFile; fileRef = 00723DD9150E8D86006847F2 /* nxsleep.h */; }; + 0074C89E1679008C005E2369 /* NXFileObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0074C89D1679008C005E2369 /* NXFileObject.cpp */; }; + 0074C90016790DBD005E2369 /* libnu.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0074C8FF16790DBD005E2369 /* libnu.a */; }; + 008840A315064F2E00625F51 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C5DCD1A14BB5E4D0077EB3A /* CoreFoundation.framework */; }; + 008840FE1506575D00625F51 /* nxapi.h in Copy Mac OS X Public Headers */ = {isa = PBXBuildFile; fileRef = 0C80A05614B64F0400FAA6BA /* nxapi.h */; }; + 008840FF1506575D00625F51 /* nxcondition.h in Copy Mac OS X Public Headers */ = {isa = PBXBuildFile; fileRef = 0CC9985E14C5DBC200484291 /* nxcondition.h */; }; + 008841001506575D00625F51 /* nxdata.h in Copy Mac OS X Public Headers */ = {isa = PBXBuildFile; fileRef = B1FE9B9214F5E29000629941 /* nxdata.h */; }; + 008841011506575D00625F51 /* nxpath.h in Copy Mac OS X Public Headers */ = {isa = PBXBuildFile; fileRef = 0C5DCD1D14BB67C70077EB3A /* nxpath.h */; }; + 008841021506575D00625F51 /* nxstring.h in Copy Mac OS X Public Headers */ = {isa = PBXBuildFile; fileRef = 0C80A04F14B64EC900FAA6BA /* nxstring.h */; }; + 008841031506575D00625F51 /* nxthread.h in Copy Mac OS X Public Headers */ = {isa = PBXBuildFile; fileRef = 0C80A05114B64EC900FAA6BA /* nxthread.h */; }; + 008841041506575D00625F51 /* nxuri.h in Copy Mac OS X Public Headers */ = {isa = PBXBuildFile; fileRef = 0C5494D114BB8543005EFB72 /* nxuri.h */; }; + 0088410F150657D000625F51 /* nx.h in Headers */ = {isa = PBXBuildFile; fileRef = 00884105150657CF00625F51 /* nx.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 00884110150657D000625F51 /* nxapi.h in Headers */ = {isa = PBXBuildFile; fileRef = 00884106150657CF00625F51 /* nxapi.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 00884111150657D000625F51 /* nxcondition.h in Headers */ = {isa = PBXBuildFile; fileRef = 00884107150657CF00625F51 /* nxcondition.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 00884112150657D000625F51 /* nxdata.h in Headers */ = {isa = PBXBuildFile; fileRef = 00884108150657CF00625F51 /* nxdata.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 00884113150657D000625F51 /* nxfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 00884109150657CF00625F51 /* nxfile.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 00884114150657D000625F51 /* nxmutablestring.h in Headers */ = {isa = PBXBuildFile; fileRef = 0088410A150657CF00625F51 /* nxmutablestring.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 00884115150657D000625F51 /* nxpath.h in Headers */ = {isa = PBXBuildFile; fileRef = 0088410B150657CF00625F51 /* nxpath.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 00884116150657D000625F51 /* nxsleep.h in Headers */ = {isa = PBXBuildFile; fileRef = 0088410C150657CF00625F51 /* nxsleep.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 00884117150657D000625F51 /* nxstring.h in Headers */ = {isa = PBXBuildFile; fileRef = 0088410D150657D000625F51 /* nxstring.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 00884118150657D000625F51 /* nxuri.h in Headers */ = {isa = PBXBuildFile; fileRef = 0088410E150657D000625F51 /* nxuri.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 00884119150657E600625F51 /* nxonce.h in Copy Mac OS X amd64 Public Headers */ = {isa = PBXBuildFile; fileRef = 0C80A06D14B6575700FAA6BA /* nxonce.h */; }; + 0088411A150657EC00625F51 /* nxonce.h in Copy Mac OS X x86 Public Headers */ = {isa = PBXBuildFile; fileRef = 0C80A08214B65B5000FAA6BA /* nxonce.h */; }; + 00B732B4151A625D00A8251C /* nxsemaphore.h in Headers */ = {isa = PBXBuildFile; fileRef = 00B732B3151A625D00A8251C /* nxsemaphore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 00B732B8151A628A00A8251C /* nxsemaphore.c in Sources */ = {isa = PBXBuildFile; fileRef = 00B732B6151A628A00A8251C /* nxsemaphore.c */; }; + 00B732B9151A628A00A8251C /* nxsemaphore.h in Headers */ = {isa = PBXBuildFile; fileRef = 00B732B7151A628A00A8251C /* nxsemaphore.h */; }; + 00B732BA151A62F300A8251C /* nxsemaphore.h in Copy Mac OS X Public Headers */ = {isa = PBXBuildFile; fileRef = 00B732B7151A628A00A8251C /* nxsemaphore.h */; }; + 00C27E901537245F008D95CD /* precomp.h in Headers */ = {isa = PBXBuildFile; fileRef = 00C27E8F1537245B008D95CD /* precomp.h */; }; + 00ED0A4617A28E1400BBA8B0 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00ED0A4517A28E1300BBA8B0 /* CoreServices.framework */; }; + 00F8A4F3150F0B9700CB104E /* version.c in Sources */ = {isa = PBXBuildFile; fileRef = 00F8A4F1150F0B9700CB104E /* version.c */; }; + 00F8A4F4150F0B9700CB104E /* version.h in Headers */ = {isa = PBXBuildFile; fileRef = 00F8A4F2150F0B9700CB104E /* version.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0C5494CF14BB8514005EFB72 /* nxuri.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C5494CE14BB8514005EFB72 /* nxuri.c */; }; + 0C5494D214BB8543005EFB72 /* nxuri.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C5494D114BB8543005EFB72 /* nxuri.h */; settings = {ATTRIBUTES = (); }; }; + 0C5DCD1914BB5DA40077EB3A /* nxstring.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C5DCD1814BB5DA40077EB3A /* nxstring.c */; }; + 0C5DCD1E14BB67C70077EB3A /* nxpath.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C5DCD1C14BB67C70077EB3A /* nxpath.c */; }; + 0C5DCD1F14BB67C70077EB3A /* nxpath.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C5DCD1D14BB67C70077EB3A /* nxpath.h */; settings = {ATTRIBUTES = (); }; }; + 0C80A05214B64EC900FAA6BA /* nxstring.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C80A04F14B64EC900FAA6BA /* nxstring.h */; settings = {ATTRIBUTES = (); }; }; + 0C80A05314B64EC900FAA6BA /* nxthread.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C80A05014B64EC900FAA6BA /* nxthread.c */; }; + 0C80A05414B64EC900FAA6BA /* nxthread.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C80A05114B64EC900FAA6BA /* nxthread.h */; settings = {ATTRIBUTES = (); }; }; + 0C80A05914B64F6400FAA6BA /* nxthread.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C80A05814B64F6400FAA6BA /* nxthread.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0C80A06F14B6575700FAA6BA /* nxonce.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C80A06D14B6575700FAA6BA /* nxonce.h */; }; + 0C80A08014B658C000FAA6BA /* nxonce.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C80A07F14B658C000FAA6BA /* nxonce.c */; }; + 0C80A08314B65B5000FAA6BA /* nxonce.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C80A08114B65B5000FAA6BA /* nxonce.c */; }; + 0C80A08414B65B5000FAA6BA /* nxonce.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C80A08214B65B5000FAA6BA /* nxonce.h */; }; + 0C80A08A14B65C6800FAA6BA /* nxonce.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C80A08914B65C6800FAA6BA /* nxonce.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0CC9985F14C5DBC200484291 /* nxcondition.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CC9985D14C5DBC200484291 /* nxcondition.c */; }; + 0CC9986014C5DBC200484291 /* nxcondition.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CC9985E14C5DBC200484291 /* nxcondition.h */; settings = {ATTRIBUTES = (); }; }; + B180783C14F48398000B9733 /* nxsleep.c in Sources */ = {isa = PBXBuildFile; fileRef = B180783B14F48398000B9733 /* nxsleep.c */; }; + B1FE9B9314F5E29000629941 /* nxdata.c in Sources */ = {isa = PBXBuildFile; fileRef = B1FE9B9114F5E29000629941 /* nxdata.c */; }; + B1FE9B9414F5E29000629941 /* nxdata.h in Headers */ = {isa = PBXBuildFile; fileRef = B1FE9B9214F5E29000629941 /* nxdata.h */; settings = {ATTRIBUTES = (); }; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 002FD394151981BC00857D4F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0CC19BF514B63FDC0095FCAE /* Project object */; + proxyType = 1; + remoteGlobalIDString = 002FD390151981B200857D4F; + remoteInfo = "nx-cleanup"; + }; + 0039B368152A1F3500D96D3E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0CC19BF514B63FDC0095FCAE /* Project object */; + proxyType = 1; + remoteGlobalIDString = 002FD390151981B200857D4F; + remoteInfo = "nx-cleanup"; + }; + 00B73407151BAE0C00A8251C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0CC19BF514B63FDC0095FCAE /* Project object */; + proxyType = 1; + remoteGlobalIDString = 00B73401151BADB700A8251C; + remoteInfo = "nx-version"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 008840FB150656FD00625F51 /* Copy Mac OS X Public Headers */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 12; + dstPath = "$(PUBLIC_HEADERS_FOLDER_PATH)/osx"; + dstSubfolderSpec = 16; + files = ( + 00512B9B156BD66500115B09 /* nxtime.h in Copy Mac OS X Public Headers */, + 00723DDB150E8D9C006847F2 /* nxsleep.h in Copy Mac OS X Public Headers */, + 00723DD8150E8CF0006847F2 /* nxfile.h in Copy Mac OS X Public Headers */, + 008840FE1506575D00625F51 /* nxapi.h in Copy Mac OS X Public Headers */, + 008840FF1506575D00625F51 /* nxcondition.h in Copy Mac OS X Public Headers */, + 008841001506575D00625F51 /* nxdata.h in Copy Mac OS X Public Headers */, + 00695D4316E86E28009CB115 /* nxlog.h in Copy Mac OS X Public Headers */, + 008841011506575D00625F51 /* nxpath.h in Copy Mac OS X Public Headers */, + 00B732BA151A62F300A8251C /* nxsemaphore.h in Copy Mac OS X Public Headers */, + 008841021506575D00625F51 /* nxstring.h in Copy Mac OS X Public Headers */, + 008841031506575D00625F51 /* nxthread.h in Copy Mac OS X Public Headers */, + 008841041506575D00625F51 /* nxuri.h in Copy Mac OS X Public Headers */, + ); + name = "Copy Mac OS X Public Headers"; + runOnlyForDeploymentPostprocessing = 0; + }; + 008840FC1506572100625F51 /* Copy Mac OS X x86 Public Headers */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 12; + dstPath = "$(PUBLIC_HEADERS_FOLDER_PATH)/osx-x86"; + dstSubfolderSpec = 16; + files = ( + 0088411A150657EC00625F51 /* nxonce.h in Copy Mac OS X x86 Public Headers */, + ); + name = "Copy Mac OS X x86 Public Headers"; + runOnlyForDeploymentPostprocessing = 0; + }; + 008840FD1506572B00625F51 /* Copy Mac OS X amd64 Public Headers */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 12; + dstPath = "$(PUBLIC_HEADERS_FOLDER_PATH)/osx-amd64"; + dstSubfolderSpec = 16; + files = ( + 00884119150657E600625F51 /* nxonce.h in Copy Mac OS X amd64 Public Headers */, + ); + name = "Copy Mac OS X amd64 Public Headers"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 00512B96156BD61500115B09 /* nxtime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nxtime.h; sourceTree = "<group>"; }; + 00512B99156BD62800115B09 /* nxtime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nxtime.h; path = osx/nxtime.h; sourceTree = "<group>"; }; + 0062CA59170B228300CBFD15 /* MessageLoop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MessageLoop.cpp; path = ../nu/osx/MessageLoop.cpp; sourceTree = "<group>"; }; + 0062CA5A170B228300CBFD15 /* MessageLoop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MessageLoop.h; path = ../nu/osx/MessageLoop.h; sourceTree = "<group>"; }; + 00695D1516E70C1A009CB115 /* NXFileProgressiveDownloader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NXFileProgressiveDownloader.cpp; path = osx/NXFileProgressiveDownloader.cpp; sourceTree = "<group>"; }; + 00695D1616E70C1A009CB115 /* nxlog.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = nxlog.c; path = osx/nxlog.c; sourceTree = "<group>"; }; + 00695D1716E70C1A009CB115 /* nxlog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nxlog.h; path = osx/nxlog.h; sourceTree = "<group>"; }; + 00695D1D16E70D19009CB115 /* nxlog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nxlog.h; sourceTree = "<group>"; }; + 00695D1F16E70D2B009CB115 /* NXFileObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NXFileObject.h; path = osx/NXFileObject.h; sourceTree = "<group>"; }; + 00695D2D16E7DEB5009CB115 /* libjnetlib-1.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = "libjnetlib-1.dylib"; sourceTree = BUILT_PRODUCTS_DIR; }; + 00723DD3150E8CCD006847F2 /* nxfile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = nxfile.c; path = osx/nxfile.c; sourceTree = "<group>"; }; + 00723DD4150E8CCD006847F2 /* nxfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nxfile.h; path = osx/nxfile.h; sourceTree = "<group>"; }; + 00723DD9150E8D86006847F2 /* nxsleep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nxsleep.h; path = osx/nxsleep.h; sourceTree = "<group>"; }; + 0073AB96150A7A7C0027A889 /* VERSION */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = VERSION; sourceTree = "<group>"; }; + 0074C89D1679008C005E2369 /* NXFileObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NXFileObject.cpp; path = osx/NXFileObject.cpp; sourceTree = "<group>"; }; + 0074C8FF16790DBD005E2369 /* libnu.a */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.objfile"; path = libnu.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 00884105150657CF00625F51 /* nx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nx.h; sourceTree = "<group>"; }; + 00884106150657CF00625F51 /* nxapi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nxapi.h; sourceTree = "<group>"; }; + 00884107150657CF00625F51 /* nxcondition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nxcondition.h; sourceTree = "<group>"; }; + 00884108150657CF00625F51 /* nxdata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nxdata.h; sourceTree = "<group>"; }; + 00884109150657CF00625F51 /* nxfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nxfile.h; sourceTree = "<group>"; }; + 0088410A150657CF00625F51 /* nxmutablestring.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nxmutablestring.h; sourceTree = "<group>"; }; + 0088410B150657CF00625F51 /* nxpath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nxpath.h; sourceTree = "<group>"; }; + 0088410C150657CF00625F51 /* nxsleep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nxsleep.h; sourceTree = "<group>"; }; + 0088410D150657D000625F51 /* nxstring.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nxstring.h; sourceTree = "<group>"; }; + 0088410E150657D000625F51 /* nxuri.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nxuri.h; sourceTree = "<group>"; }; + 0092A7AA17A30C6400E0ECD8 /* CarbonCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CarbonCore.framework; path = ../../../../../System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework; sourceTree = "<group>"; }; + 00B732B3151A625D00A8251C /* nxsemaphore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nxsemaphore.h; sourceTree = "<group>"; }; + 00B732B6151A628A00A8251C /* nxsemaphore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = nxsemaphore.c; path = osx/nxsemaphore.c; sourceTree = "<group>"; }; + 00B732B7151A628A00A8251C /* nxsemaphore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nxsemaphore.h; path = osx/nxsemaphore.h; sourceTree = "<group>"; }; + 00C27E8F1537245B008D95CD /* precomp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = precomp.h; sourceTree = "<group>"; }; + 00ED0A4517A28E1300BBA8B0 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; }; + 00F8A4F1150F0B9700CB104E /* version.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = version.c; path = $PROJECT_DERIVED_FILE_DIR/version.c; sourceTree = "<absolute>"; }; + 00F8A4F2150F0B9700CB104E /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = version.h; path = $PROJECT_DERIVED_FILE_DIR/version.h; sourceTree = "<absolute>"; }; + 0C5494CE14BB8514005EFB72 /* nxuri.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = nxuri.c; path = osx/nxuri.c; sourceTree = "<group>"; }; + 0C5494D114BB8543005EFB72 /* nxuri.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nxuri.h; path = osx/nxuri.h; sourceTree = "<group>"; }; + 0C5DCD1814BB5DA40077EB3A /* nxstring.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = nxstring.c; path = osx/nxstring.c; sourceTree = "<group>"; }; + 0C5DCD1A14BB5E4D0077EB3A /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; + 0C5DCD1C14BB67C70077EB3A /* nxpath.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = nxpath.c; path = osx/nxpath.c; sourceTree = "<group>"; }; + 0C5DCD1D14BB67C70077EB3A /* nxpath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nxpath.h; path = osx/nxpath.h; sourceTree = "<group>"; }; + 0C80A04F14B64EC900FAA6BA /* nxstring.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nxstring.h; path = osx/nxstring.h; sourceTree = "<group>"; }; + 0C80A05014B64EC900FAA6BA /* nxthread.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = nxthread.c; path = osx/nxthread.c; sourceTree = "<group>"; }; + 0C80A05114B64EC900FAA6BA /* nxthread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nxthread.h; path = osx/nxthread.h; sourceTree = "<group>"; }; + 0C80A05614B64F0400FAA6BA /* nxapi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nxapi.h; path = osx/nxapi.h; sourceTree = "<group>"; }; + 0C80A05814B64F6400FAA6BA /* nxthread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nxthread.h; sourceTree = "<group>"; }; + 0C80A06D14B6575700FAA6BA /* nxonce.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nxonce.h; path = "osx-amd64/nxonce.h"; sourceTree = "<group>"; }; + 0C80A07F14B658C000FAA6BA /* nxonce.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = nxonce.c; path = "osx-amd64/nxonce.c"; sourceTree = "<group>"; }; + 0C80A08114B65B5000FAA6BA /* nxonce.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = nxonce.c; path = "osx-x86/nxonce.c"; sourceTree = "<group>"; }; + 0C80A08214B65B5000FAA6BA /* nxonce.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nxonce.h; path = "osx-x86/nxonce.h"; sourceTree = "<group>"; }; + 0C80A08914B65C6800FAA6BA /* nxonce.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nxonce.h; sourceTree = "<group>"; }; + 0CC19BFE14B63FDC0095FCAE /* libnx-1.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = "libnx-1.dylib"; sourceTree = BUILT_PRODUCTS_DIR; }; + 0CC9985D14C5DBC200484291 /* nxcondition.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = nxcondition.c; path = osx/nxcondition.c; sourceTree = "<group>"; }; + 0CC9985E14C5DBC200484291 /* nxcondition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nxcondition.h; path = osx/nxcondition.h; sourceTree = "<group>"; }; + B180783B14F48398000B9733 /* nxsleep.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = nxsleep.c; path = osx/nxsleep.c; sourceTree = "<group>"; }; + B1FE9B9114F5E29000629941 /* nxdata.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = nxdata.c; path = osx/nxdata.c; sourceTree = "<group>"; }; + B1FE9B9214F5E29000629941 /* nxdata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nxdata.h; path = osx/nxdata.h; sourceTree = "<group>"; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 0CC19BFB14B63FDC0095FCAE /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 0074C90016790DBD005E2369 /* libnu.a in Frameworks */, + 00695D2E16E7DEB5009CB115 /* libjnetlib-1.dylib in Frameworks */, + 008840A315064F2E00625F51 /* CoreFoundation.framework in Frameworks */, + 00ED0A4617A28E1400BBA8B0 /* CoreServices.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 0062CA58170B226C00CBFD15 /* nu */ = { + isa = PBXGroup; + children = ( + 0062CA59170B228300CBFD15 /* MessageLoop.cpp */, + 0062CA5A170B228300CBFD15 /* MessageLoop.h */, + ); + name = nu; + sourceTree = "<group>"; + }; + 0074C8FD16790D81005E2369 /* Libraries */ = { + isa = PBXGroup; + children = ( + 0074C8FF16790DBD005E2369 /* libnu.a */, + 00695D2D16E7DEB5009CB115 /* libjnetlib-1.dylib */, + ); + name = Libraries; + sourceTree = "<group>"; + }; + 008840A215064EE800625F51 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 0C5DCD1A14BB5E4D0077EB3A /* CoreFoundation.framework */, + 00ED0A4517A28E1300BBA8B0 /* CoreServices.framework */, + ); + name = Frameworks; + sourceTree = "<group>"; + }; + 00F8A4F0150F0AFF00CB104E /* Version */ = { + isa = PBXGroup; + children = ( + 0073AB96150A7A7C0027A889 /* VERSION */, + 00F8A4F1150F0B9700CB104E /* version.c */, + 00F8A4F2150F0B9700CB104E /* version.h */, + ); + name = Version; + sourceTree = "<group>"; + }; + 0C80A04E14B64EB800FAA6BA /* osx */ = { + isa = PBXGroup; + children = ( + 0C80A05614B64F0400FAA6BA /* nxapi.h */, + 0CC9985D14C5DBC200484291 /* nxcondition.c */, + 0CC9985E14C5DBC200484291 /* nxcondition.h */, + B1FE9B9114F5E29000629941 /* nxdata.c */, + B1FE9B9214F5E29000629941 /* nxdata.h */, + 00723DD3150E8CCD006847F2 /* nxfile.c */, + 00723DD4150E8CCD006847F2 /* nxfile.h */, + 0074C89D1679008C005E2369 /* NXFileObject.cpp */, + 00695D1F16E70D2B009CB115 /* NXFileObject.h */, + 00695D1516E70C1A009CB115 /* NXFileProgressiveDownloader.cpp */, + 00695D1616E70C1A009CB115 /* nxlog.c */, + 00695D1716E70C1A009CB115 /* nxlog.h */, + 0C5DCD1C14BB67C70077EB3A /* nxpath.c */, + 0C5DCD1D14BB67C70077EB3A /* nxpath.h */, + 00B732B6151A628A00A8251C /* nxsemaphore.c */, + 00B732B7151A628A00A8251C /* nxsemaphore.h */, + B180783B14F48398000B9733 /* nxsleep.c */, + 00723DD9150E8D86006847F2 /* nxsleep.h */, + 0C5DCD1814BB5DA40077EB3A /* nxstring.c */, + 0C80A04F14B64EC900FAA6BA /* nxstring.h */, + 0C80A05014B64EC900FAA6BA /* nxthread.c */, + 0C80A05114B64EC900FAA6BA /* nxthread.h */, + 00512B99156BD62800115B09 /* nxtime.h */, + 0C5494CE14BB8514005EFB72 /* nxuri.c */, + 0C5494D114BB8543005EFB72 /* nxuri.h */, + ); + name = osx; + sourceTree = "<group>"; + }; + 0CC19BF314B63FDC0095FCAE = { + isa = PBXGroup; + children = ( + 0092A7AA17A30C6400E0ECD8 /* CarbonCore.framework */, + 00695D1D16E70D19009CB115 /* nxlog.h */, + 00512B96156BD61500115B09 /* nxtime.h */, + 00C27E8F1537245B008D95CD /* precomp.h */, + 00884105150657CF00625F51 /* nx.h */, + 00884106150657CF00625F51 /* nxapi.h */, + 00884107150657CF00625F51 /* nxcondition.h */, + 00884108150657CF00625F51 /* nxdata.h */, + 00884109150657CF00625F51 /* nxfile.h */, + 0088410A150657CF00625F51 /* nxmutablestring.h */, + 0C80A08914B65C6800FAA6BA /* nxonce.h */, + 0088410B150657CF00625F51 /* nxpath.h */, + 0088410C150657CF00625F51 /* nxsleep.h */, + 00B732B3151A625D00A8251C /* nxsemaphore.h */, + 0088410D150657D000625F51 /* nxstring.h */, + 0C80A05814B64F6400FAA6BA /* nxthread.h */, + 0088410E150657D000625F51 /* nxuri.h */, + 0C80A04E14B64EB800FAA6BA /* osx */, + 0CC19C1414B640810095FCAE /* amd64 */, + 0CC19C1314B6407A0095FCAE /* x86 */, + 0062CA58170B226C00CBFD15 /* nu */, + 00F8A4F0150F0AFF00CB104E /* Version */, + 0074C8FD16790D81005E2369 /* Libraries */, + 008840A215064EE800625F51 /* Frameworks */, + 0CC19BFF14B63FDC0095FCAE /* Products */, + ); + sourceTree = "<group>"; + }; + 0CC19BFF14B63FDC0095FCAE /* Products */ = { + isa = PBXGroup; + children = ( + 0CC19BFE14B63FDC0095FCAE /* libnx-1.dylib */, + ); + name = Products; + sourceTree = "<group>"; + }; + 0CC19C1314B6407A0095FCAE /* x86 */ = { + isa = PBXGroup; + children = ( + 0C80A08114B65B5000FAA6BA /* nxonce.c */, + 0C80A08214B65B5000FAA6BA /* nxonce.h */, + ); + name = x86; + sourceTree = "<group>"; + }; + 0CC19C1414B640810095FCAE /* amd64 */ = { + isa = PBXGroup; + children = ( + 0C80A06D14B6575700FAA6BA /* nxonce.h */, + 0C80A07F14B658C000FAA6BA /* nxonce.c */, + ); + name = amd64; + sourceTree = "<group>"; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 0CC19BFC14B63FDC0095FCAE /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 0C80A05214B64EC900FAA6BA /* nxstring.h in Headers */, + 0C80A05414B64EC900FAA6BA /* nxthread.h in Headers */, + 0C80A05914B64F6400FAA6BA /* nxthread.h in Headers */, + 0C80A06F14B6575700FAA6BA /* nxonce.h in Headers */, + 0C80A08414B65B5000FAA6BA /* nxonce.h in Headers */, + 0C80A08A14B65C6800FAA6BA /* nxonce.h in Headers */, + 0C5DCD1F14BB67C70077EB3A /* nxpath.h in Headers */, + 0C5494D214BB8543005EFB72 /* nxuri.h in Headers */, + 0CC9986014C5DBC200484291 /* nxcondition.h in Headers */, + B1FE9B9414F5E29000629941 /* nxdata.h in Headers */, + 0088410F150657D000625F51 /* nx.h in Headers */, + 00884110150657D000625F51 /* nxapi.h in Headers */, + 00884111150657D000625F51 /* nxcondition.h in Headers */, + 00884112150657D000625F51 /* nxdata.h in Headers */, + 00884113150657D000625F51 /* nxfile.h in Headers */, + 00884114150657D000625F51 /* nxmutablestring.h in Headers */, + 00884115150657D000625F51 /* nxpath.h in Headers */, + 00884116150657D000625F51 /* nxsleep.h in Headers */, + 00884117150657D000625F51 /* nxstring.h in Headers */, + 00884118150657D000625F51 /* nxuri.h in Headers */, + 00723DD6150E8CCD006847F2 /* nxfile.h in Headers */, + 00723DDA150E8D86006847F2 /* nxsleep.h in Headers */, + 00F8A4F4150F0B9700CB104E /* version.h in Headers */, + 00B732B4151A625D00A8251C /* nxsemaphore.h in Headers */, + 00B732B9151A628A00A8251C /* nxsemaphore.h in Headers */, + 00C27E901537245F008D95CD /* precomp.h in Headers */, + 00512B97156BD61500115B09 /* nxtime.h in Headers */, + 00512B9A156BD62800115B09 /* nxtime.h in Headers */, + 00695D1A16E70C1A009CB115 /* nxlog.h in Headers */, + 00695D1E16E70D19009CB115 /* nxlog.h in Headers */, + 00695D2016E70D2B009CB115 /* NXFileObject.h in Headers */, + 0062CA5C170B228300CBFD15 /* MessageLoop.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXLegacyTarget section */ + 002FD390151981B200857D4F /* nx-cleanup */ = { + isa = PBXLegacyTarget; + buildArgumentsString = "$(NSBUILD_TOOLS_BIN_DIR)/cleanbuild --xcode-mode --libraries \"$(LIBRARY_PATH)\" \"$(PUBLIC_HEADERS_DIR)\" \"$(DWARF_DSYM_PATH)\" \"$(PROJECT_DERIVED_FILE_DIR)/version.*\""; + buildConfigurationList = 002FD391151981B200857D4F /* Build configuration list for PBXLegacyTarget "nx-cleanup" */; + buildPhases = ( + ); + buildToolPath = /bin/sh; + buildWorkingDirectory = ""; + dependencies = ( + ); + name = "nx-cleanup"; + passBuildSettingsInEnvironment = 1; + productName = "nx-cleanup"; + }; +/* End PBXLegacyTarget section */ + +/* Begin PBXNativeTarget section */ + 0CC19BFD14B63FDC0095FCAE /* nx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0CC19C0214B63FDC0095FCAE /* Build configuration list for PBXNativeTarget "nx" */; + buildPhases = ( + 0CC19BFA14B63FDC0095FCAE /* Sources */, + 0CC19BFB14B63FDC0095FCAE /* Frameworks */, + 00C80456150FCB33005570B4 /* Create Symbolic Links */, + 0CC19BFC14B63FDC0095FCAE /* Headers */, + 008840FB150656FD00625F51 /* Copy Mac OS X Public Headers */, + 008840FD1506572B00625F51 /* Copy Mac OS X amd64 Public Headers */, + 008840FC1506572100625F51 /* Copy Mac OS X x86 Public Headers */, + 0073ABB5150E69E20027A889 /* Install Public Headers */, + 002FD36A15126B7400857D4F /* Install Debug Symbols */, + ); + buildRules = ( + ); + dependencies = ( + 002FD395151981BC00857D4F /* PBXTargetDependency */, + 00B73408151BAE0C00A8251C /* PBXTargetDependency */, + ); + name = nx; + productName = nx; + productReference = 0CC19BFE14B63FDC0095FCAE /* libnx-1.dylib */; + productType = "com.apple.product-type.library.dynamic"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 0CC19BF514B63FDC0095FCAE /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0500; + ORGANIZATIONNAME = "Nullsoft, Inc."; + }; + buildConfigurationList = 0CC19BF814B63FDC0095FCAE /* Build configuration list for PBXProject "nx" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 0CC19BF314B63FDC0095FCAE; + productRefGroup = 0CC19BFF14B63FDC0095FCAE /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 0CC19BFD14B63FDC0095FCAE /* nx */, + 002FD390151981B200857D4F /* nx-cleanup */, + 00B73401151BADB700A8251C /* nx-prepare */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXShellScriptBuildPhase section */ + 002FD36A15126B7400857D4F /* Install Debug Symbols */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 8; + files = ( + ); + inputPaths = ( + "$(DWARF_DSYM_FOLDER_PATH)/$(DWARF_DSYM_FILE_NAME)", + ); + name = "Install Debug Symbols"; + outputPaths = ( + "$(DWARF_DSYM_INSTALL_FOLDER_PATH)/$(DWARF_DSYM_FILE_NAME)", + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = "INSTALLTOOL=\"$NSBUILD_TOOLS_BIN_DIR/installtool\"\n$INSTALLTOOL \"$SCRIPT_INPUT_FILE_0/\" \\\n \"$SCRIPT_OUTPUT_FILE_0\"\n"; + showEnvVarsInLog = 0; + }; + 0073ABB5150E69E20027A889 /* Install Public Headers */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 8; + files = ( + ); + inputPaths = ( + "$(BUILT_PRODUCTS_DIR)$(PUBLIC_HEADERS_FOLDER_PATH)", + ); + name = "Install Public Headers"; + outputPaths = ( + "$(DSTROOT)$(PUBLIC_HEADERS_FOLDER_PATH)", + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = "INSTALLTOOL=\"$NSBUILD_TOOLS_BIN_DIR/installtool\"\n$INSTALLTOOL --headers-only \\\n \"$SCRIPT_INPUT_FILE_0/\" \\\n \"$SCRIPT_OUTPUT_FILE_0\"\n"; + showEnvVarsInLog = 0; + }; + 00B73405151BADCC00A8251C /* Generate Version Info */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "$(SRCROOT)/VERSION", + "$(NSBUILD_TOOLS_SHARE_DIR)/nvgtool/dylib-version.template.h", + "$(NSBUILD_TOOLS_SHARE_DIR)/nvgtool/dylib-version.template.c", + ); + name = "Generate Version Info"; + outputPaths = ( + "$(PROJECT_DERIVED_FILE_DIR)/version.h", + "$(PROJECT_DERIVED_FILE_DIR)/version.c", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "PRODUCT_VERSION=$(cat \"$SCRIPT_INPUT_FILE_0\")\n\nif [ ! -d \"$PROJECT_DERIVED_FILE_DIR\" ]; then\n mkdir -p \"$PROJECT_DERIVED_FILE_DIR\"\nfi\n\nNVGTOOL=\"$NSBUILD_TOOLS_BIN_DIR/nvgtool\"\n$NVGTOOL --product-name \"$PRODUCT_NAME\" \\\n --product-version \"$PRODUCT_VERSION\" \\\n --input-file \"$SCRIPT_INPUT_FILE_1\" \\\n --output-file \"$SCRIPT_OUTPUT_FILE_0\"\n\n$NVGTOOL --product-name \"$PRODUCT_NAME\" \\\n --product-version \"$PRODUCT_VERSION\" \\\n --input-file \"$SCRIPT_INPUT_FILE_2\" \\\n --output-file \"$SCRIPT_OUTPUT_FILE_1\""; + showEnvVarsInLog = 0; + }; + 00C80456150FCB33005570B4 /* Create Symbolic Links */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 12; + files = ( + ); + inputPaths = ( + "$(TARGET_BUILD_DIR)/$(EXECUTABLE_NAME)", + ); + name = "Create Symbolic Links"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "LIBLN=\"$NSBUILD_TOOLS_BIN_DIR/libln\"\ncd $TARGET_BUILD_DIR; \\\n$LIBLN \"$EXECUTABLE_NAME\"\n\nif [ \"$DEPLOYMENT_LOCATION\" == \"YES\" ]; then\n cd \"$BUILT_PRODUCTS_DIR\"; \\\n $LIBLN \"$EXECUTABLE_NAME\"\nfi"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 0CC19BFA14B63FDC0095FCAE /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0C80A05314B64EC900FAA6BA /* nxthread.c in Sources */, + 0C80A08014B658C000FAA6BA /* nxonce.c in Sources */, + 0C80A08314B65B5000FAA6BA /* nxonce.c in Sources */, + 0C5DCD1914BB5DA40077EB3A /* nxstring.c in Sources */, + 0C5DCD1E14BB67C70077EB3A /* nxpath.c in Sources */, + 0C5494CF14BB8514005EFB72 /* nxuri.c in Sources */, + 0CC9985F14C5DBC200484291 /* nxcondition.c in Sources */, + B180783C14F48398000B9733 /* nxsleep.c in Sources */, + B1FE9B9314F5E29000629941 /* nxdata.c in Sources */, + 00723DD5150E8CCD006847F2 /* nxfile.c in Sources */, + 00F8A4F3150F0B9700CB104E /* version.c in Sources */, + 00B732B8151A628A00A8251C /* nxsemaphore.c in Sources */, + 0074C89E1679008C005E2369 /* NXFileObject.cpp in Sources */, + 00695D1816E70C1A009CB115 /* NXFileProgressiveDownloader.cpp in Sources */, + 00695D1916E70C1A009CB115 /* nxlog.c in Sources */, + 0062CA5B170B228300CBFD15 /* MessageLoop.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 002FD395151981BC00857D4F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 002FD390151981B200857D4F /* nx-cleanup */; + targetProxy = 002FD394151981BC00857D4F /* PBXContainerItemProxy */; + }; + 0039B369152A1F3500D96D3E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 002FD390151981B200857D4F /* nx-cleanup */; + targetProxy = 0039B368152A1F3500D96D3E /* PBXContainerItemProxy */; + }; + 00B73408151BAE0C00A8251C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 00B73401151BADB700A8251C /* nx-prepare */; + targetProxy = 00B73407151BAE0C00A8251C /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 002FD392151981B200857D4F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + DWARF_DSYM_PATH = "$(BUILT_PRODUCTS_DIR)/$(EXECUTABLE_NAME).dSYM"; + LIBRARY_PATH = "$(BUILT_PRODUCTS_DIR)/$(EXECUTABLE_NAME)"; + PUBLIC_HEADERS_DIR = "$(BUILT_PRODUCTS_DIR)$(PUBLIC_HEADERS_FOLDER_PATH)"; + }; + name = Debug; + }; + 002FD393151981B200857D4F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + DWARF_DSYM_PATH = "$(BUILT_PRODUCTS_DIR)/$(EXECUTABLE_NAME).dSYM"; + LIBRARY_PATH = "$(BUILT_PRODUCTS_DIR)/$(EXECUTABLE_NAME)"; + PUBLIC_HEADERS_DIR = "$(BUILT_PRODUCTS_DIR)$(PUBLIC_HEADERS_FOLDER_PATH)"; + }; + name = Release; + }; + 00B73403151BADB700A8251C /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Debug; + }; + 00B73404151BADB700A8251C /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Release; + }; + 0CC19C0014B63FDC0095FCAE /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DWARF_DSYM_INSTALL_FOLDER_PATH = "$(INSTALL_ROOT)$(INSTALL_PATH_PREFIX)/symbols"; + DYLIB_COMPATIBILITY_VERSION = "$(CURRENT_PROJECT_VERSION)"; + DYLIB_CURRENT_VERSION = "$(CURRENT_PROJECT_VERSION)"; + EXECUTABLE_EXTENSION = dylib; + EXECUTABLE_NAME = "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)-$(DYLIB_CURRENT_VERSION).$(EXECUTABLE_EXTENSION)"; + EXECUTABLE_PREFIX = lib; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_INCREASE_PRECOMPILED_HEADER_SHARING = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = precomp.h; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INSTALL_PATH = "$(INSTALL_PATH_PREFIX)/lib/"; + INSTALL_PATH_PREFIX = /usr/local; + LD_DYLIB_INSTALL_NAME = "@rpath/$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)-$(DYLIB_COMPATIBILITY_VERSION).$(EXECUTABLE_EXTENSION)"; + MACH_O_TYPE = mh_dylib; + MACOSX_DEPLOYMENT_TARGET = 10.6; + NSBUILD_TOOLS_BIN_DIR = "$(NSBUILD_TOOLS_DIR)/bin"; + NSBUILD_TOOLS_DIR = "$(SRCROOT)/../../build-tools"; + NSBUILD_TOOLS_SHARE_DIR = "$(NSBUILD_TOOLS_DIR)/share"; + ONLY_ACTIVE_ARCH = YES; + PRIVATE_HEADERS_FOLDER_PATH = "$(INSTALL_PATH_PREFIX)/include/$(PRODUCT_NAME)"; + PRODUCT_NAME = "$(PROJECT_NAME)"; + PUBLIC_HEADERS_FOLDER_PATH = "$(INSTALL_PATH_PREFIX)/include/$(PRODUCT_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ".. $(BUILT_PRODUCTS_DIR)$(INSTALL_PATH_PREFIX)/include"; + }; + name = Debug; + }; + 0CC19C0114B63FDC0095FCAE /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DWARF_DSYM_INSTALL_FOLDER_PATH = "$(INSTALL_ROOT)$(INSTALL_PATH_PREFIX)/symbols"; + DYLIB_COMPATIBILITY_VERSION = "$(CURRENT_PROJECT_VERSION)"; + DYLIB_CURRENT_VERSION = "$(CURRENT_PROJECT_VERSION)"; + EXECUTABLE_EXTENSION = dylib; + EXECUTABLE_NAME = "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)-$(DYLIB_CURRENT_VERSION).$(EXECUTABLE_EXTENSION)"; + EXECUTABLE_PREFIX = lib; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_INCREASE_PRECOMPILED_HEADER_SHARING = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = precomp.h; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INSTALL_PATH = "$(INSTALL_PATH_PREFIX)/lib/"; + INSTALL_PATH_PREFIX = /usr/local; + LD_DYLIB_INSTALL_NAME = "@rpath/$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)-$(DYLIB_COMPATIBILITY_VERSION).$(EXECUTABLE_EXTENSION)"; + MACH_O_TYPE = mh_dylib; + MACOSX_DEPLOYMENT_TARGET = 10.6; + NSBUILD_TOOLS_BIN_DIR = "$(NSBUILD_TOOLS_DIR)/bin"; + NSBUILD_TOOLS_DIR = "$(SRCROOT)/../../build-tools"; + NSBUILD_TOOLS_SHARE_DIR = "$(NSBUILD_TOOLS_DIR)/share"; + PRIVATE_HEADERS_FOLDER_PATH = "$(INSTALL_PATH_PREFIX)/include/$(PRODUCT_NAME)"; + PRODUCT_NAME = "$(PROJECT_NAME)"; + PUBLIC_HEADERS_FOLDER_PATH = "$(INSTALL_PATH_PREFIX)/include/$(PRODUCT_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ".. $(BUILT_PRODUCTS_DIR)$(INSTALL_PATH_PREFIX)/include"; + }; + name = Release; + }; + 0CC19C0314B63FDC0095FCAE /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks\"", + ); + GCC_INCREASE_PRECOMPILED_HEADER_SHARING = NO; + GCC_PRECOMPILE_PREFIX_HEADER = NO; + }; + name = Debug; + }; + 0CC19C0414B63FDC0095FCAE /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks\"", + ); + GCC_INCREASE_PRECOMPILED_HEADER_SHARING = NO; + GCC_PRECOMPILE_PREFIX_HEADER = NO; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 002FD391151981B200857D4F /* Build configuration list for PBXLegacyTarget "nx-cleanup" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 002FD392151981B200857D4F /* Debug */, + 002FD393151981B200857D4F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 00B73402151BADB700A8251C /* Build configuration list for PBXAggregateTarget "nx-prepare" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 00B73403151BADB700A8251C /* Debug */, + 00B73404151BADB700A8251C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0CC19BF814B63FDC0095FCAE /* Build configuration list for PBXProject "nx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0CC19C0014B63FDC0095FCAE /* Debug */, + 0CC19C0114B63FDC0095FCAE /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0CC19C0214B63FDC0095FCAE /* Build configuration list for PBXNativeTarget "nx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0CC19C0314B63FDC0095FCAE /* Debug */, + 0CC19C0414B63FDC0095FCAE /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 0CC19BF514B63FDC0095FCAE /* Project object */; +} diff --git a/Src/replicant/nx/nx.xcodeproj/xcshareddata/xcschemes/nx.xcscheme b/Src/replicant/nx/nx.xcodeproj/xcshareddata/xcschemes/nx.xcscheme new file mode 100644 index 00000000..98d012c4 --- /dev/null +++ b/Src/replicant/nx/nx.xcodeproj/xcshareddata/xcschemes/nx.xcscheme @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Scheme + LastUpgradeVersion = "0500" + version = "1.3"> + <BuildAction + parallelizeBuildables = "YES" + buildImplicitDependencies = "YES"> + <BuildActionEntries> + <BuildActionEntry + buildForTesting = "YES" + buildForRunning = "YES" + buildForProfiling = "YES" + buildForArchiving = "YES" + buildForAnalyzing = "YES"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "0CC19BFD14B63FDC0095FCAE" + BuildableName = "libnx-1.dylib" + BlueprintName = "nx" + ReferencedContainer = "container:nx.xcodeproj"> + </BuildableReference> + </BuildActionEntry> + </BuildActionEntries> + </BuildAction> + <TestAction + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + shouldUseLaunchSchemeArgsEnv = "YES" + buildConfiguration = "Debug"> + <Testables> + </Testables> + </TestAction> + <LaunchAction + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + launchStyle = "0" + useCustomWorkingDirectory = "NO" + buildConfiguration = "Debug" + ignoresPersistentStateOnLaunch = "NO" + debugDocumentVersioning = "YES" + allowLocationSimulation = "YES"> + <AdditionalOptions> + </AdditionalOptions> + </LaunchAction> + <ProfileAction + shouldUseLaunchSchemeArgsEnv = "YES" + savedToolIdentifier = "" + useCustomWorkingDirectory = "NO" + buildConfiguration = "Release" + debugDocumentVersioning = "YES"> + </ProfileAction> + <AnalyzeAction + buildConfiguration = "Debug"> + </AnalyzeAction> + <ArchiveAction + buildConfiguration = "Release" + revealArchiveInOrganizer = "YES"> + </ArchiveAction> +</Scheme> diff --git a/Src/replicant/nx/nx.xcworkspace/contents.xcworkspacedata b/Src/replicant/nx/nx.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..d2ee22ef --- /dev/null +++ b/Src/replicant/nx/nx.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Workspace + version = "1.0"> + <FileRef + location = "group:../foundation/foundation.xcodeproj"> + </FileRef> + <FileRef + location = "group:../nu/nu.xcodeproj"> + </FileRef> + <FileRef + location = "group:../jnetlib/jnetlib.xcodeproj"> + </FileRef> + <FileRef + location = "group:nx.xcodeproj"> + </FileRef> +</Workspace> diff --git a/Src/replicant/nx/nx.xcworkspace/xcshareddata/xcschemes/nx-complete.xcscheme b/Src/replicant/nx/nx.xcworkspace/xcshareddata/xcschemes/nx-complete.xcscheme new file mode 100644 index 00000000..55220a78 --- /dev/null +++ b/Src/replicant/nx/nx.xcworkspace/xcshareddata/xcschemes/nx-complete.xcscheme @@ -0,0 +1,87 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Scheme + LastUpgradeVersion = "0440" + version = "1.3"> + <BuildAction + parallelizeBuildables = "YES" + buildImplicitDependencies = "YES"> + <BuildActionEntries> + <BuildActionEntry + buildForTesting = "YES" + buildForRunning = "YES" + buildForProfiling = "YES" + buildForArchiving = "YES" + buildForAnalyzing = "YES"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "0088424E150716D200625F51" + BuildableName = "foundation" + BlueprintName = "foundation" + ReferencedContainer = "container:../foundation/foundation.xcodeproj"> + </BuildableReference> + </BuildActionEntry> + <BuildActionEntry + buildForTesting = "YES" + buildForRunning = "YES" + buildForProfiling = "YES" + buildForArchiving = "YES" + buildForAnalyzing = "YES"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "0039B398152A384100D96D3E" + BuildableName = "libnu.a" + BlueprintName = "nu" + ReferencedContainer = "container:../nu/nu.xcodeproj"> + </BuildableReference> + </BuildActionEntry> + <BuildActionEntry + buildForTesting = "YES" + buildForRunning = "YES" + buildForProfiling = "YES" + buildForArchiving = "YES" + buildForAnalyzing = "YES"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "0CC19BFD14B63FDC0095FCAE" + BuildableName = "libnx-1.dylib" + BlueprintName = "nx" + ReferencedContainer = "container:nx.xcodeproj"> + </BuildableReference> + </BuildActionEntry> + </BuildActionEntries> + </BuildAction> + <TestAction + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + shouldUseLaunchSchemeArgsEnv = "YES" + buildConfiguration = "Debug"> + <Testables> + </Testables> + </TestAction> + <LaunchAction + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + launchStyle = "0" + useCustomWorkingDirectory = "NO" + buildConfiguration = "Debug" + ignoresPersistentStateOnLaunch = "NO" + debugDocumentVersioning = "YES" + allowLocationSimulation = "YES"> + <AdditionalOptions> + </AdditionalOptions> + </LaunchAction> + <ProfileAction + shouldUseLaunchSchemeArgsEnv = "YES" + savedToolIdentifier = "" + useCustomWorkingDirectory = "NO" + buildConfiguration = "Release" + debugDocumentVersioning = "YES"> + </ProfileAction> + <AnalyzeAction + buildConfiguration = "Debug"> + </AnalyzeAction> + <ArchiveAction + buildConfiguration = "Release" + revealArchiveInOrganizer = "YES"> + </ArchiveAction> +</Scheme> diff --git a/Src/replicant/nx/nxapi.h b/Src/replicant/nx/nxapi.h new file mode 100644 index 00000000..de5433ae --- /dev/null +++ b/Src/replicant/nx/nxapi.h @@ -0,0 +1,12 @@ +#pragma once +#if defined(__ANDROID__) +#include "android/nxapi.h" +#elif defined(__linux__) +#include "linux/nxapi.h" +#elif defined(_WIN32) +#include "win/nxapi.h" +#elif defined(__APPLE__) +#include "osx/nxapi.h" +#else +#error port me! +#endif diff --git a/Src/replicant/nx/nxcondition.h b/Src/replicant/nx/nxcondition.h new file mode 100644 index 00000000..42cfead5 --- /dev/null +++ b/Src/replicant/nx/nxcondition.h @@ -0,0 +1,10 @@ +#pragma once +#if defined(__ANDROID__) +#include "android/nxcondition.h" +#elif defined(_WIN32) +#include "win/nxcondition.h" +#elif defined(__APPLE__) +#include "osx/nxcondition.h" +#elif defined(__linux__) +#include "linux/nxcondition.h" +#endif diff --git a/Src/replicant/nx/nxdata.h b/Src/replicant/nx/nxdata.h new file mode 100644 index 00000000..721601a9 --- /dev/null +++ b/Src/replicant/nx/nxdata.h @@ -0,0 +1,10 @@ +#pragma once +#if defined(__ANDROID__) +#include "android/nxdata.h" +#elif defined(__linux__) +#include "linux/nxdata.h" +#elif defined(_WIN32) +#include "win/nxdata.h" +#elif defined(__APPLE__) +#include "osx/nxdata.h" +#endif diff --git a/Src/replicant/nx/nxfile.h b/Src/replicant/nx/nxfile.h new file mode 100644 index 00000000..4f778acf --- /dev/null +++ b/Src/replicant/nx/nxfile.h @@ -0,0 +1,10 @@ +#pragma once +#if defined(__ANDROID__) +#include "android/nxfile.h" +#elif defined(__linux__) +#include "linux/nxfile.h" +#elif defined(_WIN32) +#include "win/nxfile.h" +#elif defined(__APPLE__) +#include "osx/nxfile.h" +#endif diff --git a/Src/replicant/nx/nximage.h b/Src/replicant/nx/nximage.h new file mode 100644 index 00000000..f6a1cf4f --- /dev/null +++ b/Src/replicant/nx/nximage.h @@ -0,0 +1,4 @@ +#pragma once + +/* benski> this is a work in a progress and might go away at any point */ +#include "win/nximage.h" diff --git a/Src/replicant/nx/nxlog.h b/Src/replicant/nx/nxlog.h new file mode 100644 index 00000000..57a0a0e6 --- /dev/null +++ b/Src/replicant/nx/nxlog.h @@ -0,0 +1,10 @@ +#pragma once +#if defined(__ANDROID__) +#include "android/nxlog.h" +#elif defined(__linux__) +#include "linux/nxlog.h" +#elif defined(_WIN32) +#include "win/nxlog.h" +#elif defined(__APPLE__) +#include "osx/nxlog.h" +#endif diff --git a/Src/replicant/nx/nxmutablestring.h b/Src/replicant/nx/nxmutablestring.h new file mode 100644 index 00000000..100af7e9 --- /dev/null +++ b/Src/replicant/nx/nxmutablestring.h @@ -0,0 +1,10 @@ +#pragma once +#if defined(__ANDROID__) +#include "android/nxmutablestring.h" +#elif defined(__linux__) +#include "linux/nxmutablestring.h" +#elif defined(_WIN32) +#include "win/nxmutablestring.h" +#elif defined(__APPLE_) +#include "osx/nxmutablestring.h" +#endif diff --git a/Src/replicant/nx/nxonce.h b/Src/replicant/nx/nxonce.h new file mode 100644 index 00000000..4a5dc37d --- /dev/null +++ b/Src/replicant/nx/nxonce.h @@ -0,0 +1,14 @@ +#pragma once +#if defined(__ANDROID__) && defined(__ARM_ARCH_7A__) +#include "android-armv7/nxonce.h" +#elif defined(__ANDROID__) +#include "android-armv5/nxonce.h" +#elif defined(_WIN32) +#include "win/nxonce.h" +#elif defined(__APPLE__) && defined(__amd64__) +#include "osx-amd64/nxonce.h" +#elif defined(__APPLE__) && defined(__i386__) +#include "osx-x86/nxonce.h" +#elif defined(__linux__) +#include "linux/nxonce.h" +#endif diff --git a/Src/replicant/nx/nxpath.h b/Src/replicant/nx/nxpath.h new file mode 100644 index 00000000..61080cae --- /dev/null +++ b/Src/replicant/nx/nxpath.h @@ -0,0 +1,8 @@ +#pragma once +#if defined(__linux__) +#include "linux/nxpath.h" +#elif defined(_WIN32) +#include "win/nxpath.h" +#elif defined(__APPLE__) +#include "osx/nxpath.h" +#endif diff --git a/Src/replicant/nx/nxsemaphore.h b/Src/replicant/nx/nxsemaphore.h new file mode 100644 index 00000000..1baa0d9f --- /dev/null +++ b/Src/replicant/nx/nxsemaphore.h @@ -0,0 +1,10 @@ +#pragma once +#if defined(__ANDROID__) +#include "android/nxsemaphore.h" +#elif defined(_WIN32) +#include "win/nxsemaphore.h" +#elif defined(__APPLE__) +#include "osx/nxsemaphore.h" +#elif defined(__linux__) +#include "linux/nxsemaphore.h" +#endif diff --git a/Src/replicant/nx/nxsleep.h b/Src/replicant/nx/nxsleep.h new file mode 100644 index 00000000..2e404e07 --- /dev/null +++ b/Src/replicant/nx/nxsleep.h @@ -0,0 +1,8 @@ +#pragma once +#if defined(__linux__) +#include "linux/nxsleep.h" +#elif defined(_WIN32) +#include "win/nxsleep.h" +#elif defined(__APPLE__) +#include "osx/nxsleep.h" +#endif diff --git a/Src/replicant/nx/nxstring.h b/Src/replicant/nx/nxstring.h new file mode 100644 index 00000000..b4da51e2 --- /dev/null +++ b/Src/replicant/nx/nxstring.h @@ -0,0 +1,10 @@ +#pragma once +#if defined(__ANDROID__) +#include "android/nxstring.h" +#elif defined(__linux__) +#include "linux/nxstring.h" +#elif defined(_WIN32) +#include "win/nxstring.h" +#elif defined(__APPLE__) +#include "osx/nxstring.h" +#endif diff --git a/Src/replicant/nx/nxthread.h b/Src/replicant/nx/nxthread.h new file mode 100644 index 00000000..21e75110 --- /dev/null +++ b/Src/replicant/nx/nxthread.h @@ -0,0 +1,8 @@ +#pragma once +#if defined(__linux__) +#include "linux/nxthread.h" +#elif defined(_WIN32) +#include "win/nxthread.h" +#elif defined(__APPLE__) +#include "osx/nxthread.h" +#endif diff --git a/Src/replicant/nx/nxtime.h b/Src/replicant/nx/nxtime.h new file mode 100644 index 00000000..cbd629b1 --- /dev/null +++ b/Src/replicant/nx/nxtime.h @@ -0,0 +1,10 @@ +#pragma once +#if defined(__ANDROID__) +#include "android/nxtime.h" +#elif defined(__linux__) +#include "linux/nxtime.h" +#elif defined(_WIN32) +#include "win/nxtime.h" +#elif defined(__APPLE__) +#include "osx/nxtime.h" +#endif diff --git a/Src/replicant/nx/nxuri.h b/Src/replicant/nx/nxuri.h new file mode 100644 index 00000000..85decb56 --- /dev/null +++ b/Src/replicant/nx/nxuri.h @@ -0,0 +1,10 @@ +#pragma once +#if defined(__ANDROID__) +#include "android/nxuri.h" +#elif defined(__linux__) +#include "linux/nxuri.h" +#elif defined(_WIN32) +#include "win/nxuri.h" +#elif defined(__APPLE__) +#include "osx/nxuri.h" +#endif diff --git a/Src/replicant/nx/resource.h b/Src/replicant/nx/resource.h new file mode 100644 index 00000000..31853f03 --- /dev/null +++ b/Src/replicant/nx/resource.h @@ -0,0 +1,14 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by nx.rc + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/Src/replicant/nx/version.rc2 b/Src/replicant/nx/version.rc2 new file mode 100644 index 00000000..becc4bd2 --- /dev/null +++ b/Src/replicant/nx/version.rc2 @@ -0,0 +1,39 @@ + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// +#include "../../Winamp/buildType.h" +VS_VERSION_INFO VERSIONINFO + FILEVERSION WINAMP_PRODUCTVER + PRODUCTVERSION WINAMP_PRODUCTVER + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "Winamp SA" + VALUE "FileDescription", "Winamp Support Library" + VALUE "FileVersion", STR_WINAMP_PRODUCTVER + VALUE "InternalName", "nxlite.dll" + VALUE "LegalCopyright", "Copyright © 2012-2014 Winamp SA" + VALUE "LegalTrademarks", "Nullsoft and Winamp are trademarks of Winamp SA" + VALUE "OriginalFilename", "nxlite.dll" + VALUE "ProductName", "Winamp Shared Code Library" + VALUE "ProductVersion", STR_WINAMP_PRODUCTVER + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/Src/replicant/nx/win/NXFileObject.cpp b/Src/replicant/nx/win/NXFileObject.cpp new file mode 100644 index 00000000..8f1255db --- /dev/null +++ b/Src/replicant/nx/win/NXFileObject.cpp @@ -0,0 +1,525 @@ +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include <windows.h> +#include "NXFileObject.h" + +#include "nx/nxfile.h" +#include "nu/nodelist.h" +#include "foundation/atomics.h" +#include "nu/nodelist.h" +#include <errno.h> +#include <new> + +/* Windows implementation +note: for now, we're using FILE. We will eventually replace with better buffering + +TODO: deal with files opened in "append" mode */ + +NXFileObject::NXFileObject() +{ + nodelist_init(®ion_stack); + region.start = 0; + region.end = 0xFFFFFFFFFFFFFFFFULL; + position=0; + reference_count=1; + uri=0; + memset(&file_stats, 0, sizeof(file_stats)); +} + +NXFileObject::~NXFileObject() +{ + NXURIRelease(uri); + NXFileRegion *region = (NXFileRegion *)region_stack.head; + while (region) + { + NXFileRegion *next = (NXFileRegion *)region->Next; + free(region); + region = next; + } +} + +ns_error_t NXFileObject::Initialize(nx_uri_t _uri) +{ + uri = NXURIRetain(_uri); + return NErr_Success; +} + +size_t NXFileObject::Retain() +{ + return nx_atomic_inc(&reference_count); +} + +size_t NXFileObject::Release() +{ + if (!reference_count) + { + return reference_count; + } + size_t r = nx_atomic_dec_release(&reference_count); + if (!r) + { + delete(this); + } + return r; +} + +ns_error_t NXFileObject::LockRegion(uint64_t start, uint64_t end) +{ + // save the old region data + NXFileRegion *old_region = (NXFileRegion *)calloc(1, sizeof(NXFileRegion)); + if (!old_region) + { + return NErr_OutOfMemory; + } + old_region->start = region.start; + old_region->end = region.end; + nodelist_push_front(®ion_stack, old_region); + + // if we're already locked, Lock within our current region. + // The weird way the logic is done prevents overflow + if (start > region.end - region.start) + { + start = region.end; + } + else + { + start = region.start + start; + } + + if (end > region.end - region.start) + { + end = region.end; + } + else + { + end = region.start + end; + } + + region.start = start; + region.end = end; + return NErr_Success; +} + +ns_error_t NXFileObject::UnlockRegion() +{ + NXFileRegion *new_region = (NXFileRegion *)nodelist_pop_front(®ion_stack); + if (new_region) + { + region.start = new_region->start; + region.end = new_region->end; + free(new_region); + return NErr_Success; + } + else + { + return NErr_NoAction; + } +} + +ns_error_t NXFileObject::Stat(nx_file_stat_t out_stats) +{ + *out_stats = file_stats; + return NErr_Success; +} + +ns_error_t NXFileObject::Length(uint64_t *length) +{ + *length = region.end - region.start; + return NErr_Success; +} + +ns_error_t NXFileObject::EndOfFile() +{ + if (position >= region.end) + { + return NErr_True; + } + else + { + return NErr_False; + } +} +/* ----------------------------------------- */ + +class NXFileObject_FILE : public NXFileObject +{ +public: + NXFileObject_FILE(); + ~NXFileObject_FILE(); + ns_error_t Initialize(nx_uri_t uri, FILE *f, bool writable); + +private: + FILE *f; + bool writable; + + ns_error_t Read(void *buffer, size_t bytes_requested, size_t *bytes_read); + ns_error_t Write(const void *buffer, size_t bytes); + ns_error_t Seek(uint64_t position); + ns_error_t Tell(uint64_t *position); + ns_error_t PeekByte(uint8_t *byte); + ns_error_t Sync(); + ns_error_t Truncate(); +}; + +NXFileObject_FILE::NXFileObject_FILE() +{ + f = 0; + writable = false; +} + +NXFileObject_FILE::~NXFileObject_FILE() +{ + if (f) + { + fclose(f); + } +} + +ns_error_t NXFileObject_FILE::Initialize(nx_uri_t uri, FILE *_f, bool _writable) +{ + writable = _writable; + + ns_error_t ret = NXFileObject::Initialize(uri); + if (ret != NErr_Success) + { + return ret; + } + + ret = NXFile_statFILE(_f, &file_stats); + if (ret != NErr_Success) + { + return ret; + } + + region.end = file_stats.file_size; + + f = _f; + return NErr_Success; +} + +ns_error_t NXFileObject_FILE::Read(void *buffer, size_t bytes_requested, size_t *bytes_read) +{ + // if it's an "empty" read, we need to determine whether or not we're at the end of the file + if (bytes_requested == 0) + { + if (region.end == position || feof(f)) + { + return NErr_EndOfFile; + } + else + { + return NErr_Success; + } + } + + // don't read into any data after the locked region + if ((uint64_t)bytes_requested > region.end - position) + { + bytes_requested = (size_t)(region.end - position); + } + + if (bytes_requested == 0) + { + return NErr_EndOfFile; + } + + if (buffer == 0) + { + uint64_t old_position=position; + Seek(position+bytes_requested); + if (bytes_read) + { + *bytes_read = (size_t)(position - old_position); + } + return NErr_Success; + } + else + { + size_t results = fread(buffer, 1, bytes_requested, f); + if (results == 0) + { + if (feof(f)) + { + return NErr_EndOfFile; + } + else + { + return NErr_Error; + } + } + if (bytes_read) + { + *bytes_read = results; + } + position+=results; + return NErr_Success; + } +} + +ns_error_t NXFileObject_FILE::Write(const void *buffer, size_t bytes) +{ + // TODO: review this in relation to locked regions + size_t results = fwrite(buffer, 1, bytes, f); + if (results == 0) + { + return NErr_Error; + } + + position += results; + if (region.end < position) + { + region.end = position; + } + return NErr_Success; +} + +ns_error_t NXFileObject_FILE::PeekByte(uint8_t *byte) +{ + if (position == region.end) + { + return NErr_EndOfFile; + } + + int read_byte = fgetc(f); + if (read_byte != EOF) + { + ungetc(read_byte, f); + } + else + { + return NErr_EndOfFile; + } + + *byte = (uint8_t)read_byte; + return NErr_Success; +} + +ns_error_t NXFileObject_FILE::Seek(uint64_t new_position) +{ + if (!writable) + { + // doing it this way will prevent integer overflow + if (new_position > (region.end - region.start)) + { + new_position = region.end - region.start; + } + } + + if (_fseeki64(f, region.start+new_position, SEEK_SET) == 0) + { + position = region.start+new_position; + return NErr_Success; + } + else + { + return NErr_Error; + } +} + +ns_error_t NXFileObject_FILE::Tell(uint64_t *out_position) +{ + *out_position = position - region.start; + return NErr_Success; +} + +ns_error_t NXFileObject_FILE::Sync() +{ + fflush(f); + return NErr_Success; +} + +ns_error_t NXFileObject_FILE::Truncate() +{ + int fd = _fileno(f); + _chsize_s(fd, position); + return NErr_Success; +} + +/* ----------------------------------------- */ +ns_error_t NXFileOpenFile(nx_file_t *out_file, nx_uri_t filename, nx_file_FILE_flags_t flags) +{ + FILE *f = NXFile_fopen(filename, flags); + if (!f) + { + if (errno == ENOENT) + { + return NErr_FileNotFound; + } + else + { + return NErr_Error; + } + } + + NXFileObject_FILE *file_object = new (std::nothrow) NXFileObject_FILE; + if (!file_object) + { + fclose(f); + return NErr_OutOfMemory; + } + + ns_error_t ret = file_object->Initialize(filename, f, !!(flags & nx_file_FILE_writable_mask)); + if (ret != NErr_Success) + { + fclose(f); + delete file_object; + return ret; + } + + *out_file = (nx_file_t)file_object; + return NErr_Success; +} + +nx_file_t NXFileRetain(nx_file_t _f) +{ + if (!_f) + { + return 0; + } + + NXFileObject *f = (NXFileObject *)_f; + f->Retain(); + return _f; +} + +void NXFileRelease(nx_file_t _f) +{ + if (_f) + { + NXFileObject *f = (NXFileObject *)_f; + f->Release(); + } +} + +ns_error_t NXFileRead(nx_file_t _f, void *buffer, size_t bytes_requested, size_t *bytes_read) +{ + if (!_f) + { + return NErr_BadParameter; + } + + NXFileObject *f = (NXFileObject *)_f; + return f->Read(buffer, bytes_requested, bytes_read); +} + +ns_error_t NXFileSeek(nx_file_t _f, uint64_t position) +{ + if (!_f) + { + return NErr_BadParameter; + } + + NXFileObject *f = (NXFileObject *)_f; + return f->Seek(position); +} + +ns_error_t NXFileTell(nx_file_t _f, uint64_t *position) +{ + if (!_f) + { + return NErr_BadParameter; + } + + NXFileObject *f = (NXFileObject *)_f; + return f->Tell(position); +} + +ns_error_t NXFileLockRegion(nx_file_t _f, uint64_t start_position, uint64_t end_position) +{ + if (!_f) + { + return NErr_BadParameter; + } + + NXFileObject *f = (NXFileObject *)_f; + return f->LockRegion(start_position, end_position); +} + +ns_error_t NXFileUnlockRegion(nx_file_t _f) +{ + if (!_f) + { + return NErr_BadParameter; + } + + NXFileObject *f = (NXFileObject *)_f; + return f->UnlockRegion(); +} + +ns_error_t NXFileStat(nx_file_t _f, nx_file_stat_t file_stats) +{ + if (!_f) + { + return NErr_BadParameter; + } + + NXFileObject *f = (NXFileObject *)_f; + return f->Stat(file_stats); +} + +ns_error_t NXFileLength(nx_file_t _f, uint64_t *length) +{ + if (!_f) + { + return NErr_BadParameter; + } + + NXFileObject *f = (NXFileObject *)_f; + return f->Length(length); +} + +ns_error_t NXFileEndOfFile(nx_file_t _f) +{ + if (!_f) + { + return NErr_BadParameter; + } + + NXFileObject *f = (NXFileObject *)_f; + return f->EndOfFile(); +} + +ns_error_t NXFilePeekByte(nx_file_t _f, uint8_t *byte) +{ + if (!_f) + { + return NErr_BadParameter; + } + + NXFileObject *f = (NXFileObject *)_f; + return f->PeekByte(byte); +} + +ns_error_t NXFileWrite(nx_file_t _f, const void *buffer, size_t bytes) +{ + if (!_f) + { + return NErr_BadParameter; + } + + NXFileObject *f = (NXFileObject *)_f; + return f->Write(buffer, bytes); +} + +ns_error_t NXFileSync(nx_file_t _f) +{ + if (!_f) + { + return NErr_BadParameter; + } + + NXFileObject *f = (NXFileObject *)_f; + return f->Sync(); +} + +ns_error_t NXFileTruncate(nx_file_t _f) +{ + if (!_f) + { + return NErr_BadParameter; + } + + NXFileObject *f = (NXFileObject *)_f; + return f->Truncate(); +}
\ No newline at end of file diff --git a/Src/replicant/nx/win/NXFileObject.h b/Src/replicant/nx/win/NXFileObject.h new file mode 100644 index 00000000..46683bfa --- /dev/null +++ b/Src/replicant/nx/win/NXFileObject.h @@ -0,0 +1,45 @@ +#pragma once +#include "foundation/types.h" +#include "foundation/error.h" +#include "nx/nxuri.h" +#include "nx/nxfile.h" +#include "nu/nodelist.h" + +struct NXFileRegion : public queue_node_t +{ + uint64_t start; + uint64_t end; +}; + +class NXFileObject +{ +public: + size_t Retain(); + size_t Release(); + ns_error_t LockRegion(uint64_t start, uint64_t end); + ns_error_t UnlockRegion(); + ns_error_t Stat(nx_file_stat_t out_stats); + ns_error_t Length(uint64_t *length); + + virtual ns_error_t Read(void *buffer, size_t bytes_requested, size_t *bytes_read)=0; + virtual ns_error_t Write(const void *buffer, size_t bytes)=0; + virtual ns_error_t PeekByte(uint8_t *byte)=0; + virtual ns_error_t Seek(uint64_t position)=0; + virtual ns_error_t Tell(uint64_t *position)=0; + virtual ns_error_t Sync()=0; + virtual ns_error_t Truncate()=0; + + virtual ns_error_t EndOfFile(); + +protected: + NXFileObject(); + virtual ~NXFileObject(); + + nx_file_stat_s file_stats; + uint64_t position; /* note: this represents absolute position, _not_ position within the region */ + ns_error_t Initialize(nx_uri_t uri); + NXFileRegion region; + nodelist_s region_stack; + nx_uri_t uri; + volatile size_t reference_count; +};
\ No newline at end of file diff --git a/Src/replicant/nx/win/NXFileProgressiveDownloader.cpp b/Src/replicant/nx/win/NXFileProgressiveDownloader.cpp new file mode 100644 index 00000000..a8452c72 --- /dev/null +++ b/Src/replicant/nx/win/NXFileProgressiveDownloader.cpp @@ -0,0 +1,749 @@ +#include "NXFileObject.h" +#include "nu/ProgressTracker.h" +#include "nx/nxthread.h" +#include "nx/nxsleep.h" +#include "jnetlib/jnetlib.h" +#include "../nswasabi/AutoCharNX.h" +#include "nswasabi/ReferenceCounted.h" +#include "nu/MessageLoop.h" +#include <time.h> +#include <new> +#include "../../../WAT/WAT.h" + +/* TODO: benski> test this with a server that does not return content-length. I bet we could get it to work */ + +/* TODO: benski> on windows, we can use a single CreateFile HANDLE for both reading and writing + and use ReadFile(..., &overlapped) to maintain two separate file pointers + this should improve performance as they will share the same cache + _might_ have to use async I/O to get it to work (but use it synchronously by waiting on the handle after making the call + */ + +#define HTTP_BUFFER_SIZE 65536 + +class NXFileObject_ProgressiveDownloader; + +enum +{ + MESSAGE_KILL, + MESSAGE_SEEK, + MESSAGE_SIZE, + MESSAGE_ERROR, + MESSAGE_CLOSED, + MESSAGE_CONNECTED, +}; + +char MessageString[6][10] = +{ + "Kill", + "Seek", + "Size", + "Error", + "Closed", + "Connected" +}; + + +struct seek_message_t : public nu::message_node_t +{ + uint64_t start; + uint64_t end; +}; + +struct size_message_t : public nu::message_node_t +{ + uint64_t size; +}; + +struct error_message_t : public nu::message_node_t +{ + int error_code; +}; + +/* This class represents the thread that's actually downloading the content from the server */ +class ProgressiveDownload +{ +public: + ProgressiveDownload(ProgressTracker &progress_tracker, NXFileObject_ProgressiveDownloader &parent); + ~ProgressiveDownload(); + ns_error_t Initialize(nx_uri_t uri, jnl_http_t http, const char *user_agent, nx_uri_t temp_uri); + + void Seek(uint64_t start, uint64_t end); + void Close(); +private: + /* These functions are called on the local thread */ + /* These functions run on the download thread */ + static nx_thread_return_t NXTHREADCALL _ProgressiveThread(nx_thread_parameter_t param) { return ((ProgressiveDownload *)param)->ProgressiveThread(); } + nx_thread_return_t NXTHREADCALL ProgressiveThread(); + int Connect(); + void Internal_Write(const void *data, size_t data_len); + int Wait(int milliseconds); + ns_error_t SetupConnection(uint64_t start_position, uint64_t end_position); + int DoRead(void *buffer, size_t bufferlen); + void ProcessMessage(nu::message_node_t *message); +private: + ProgressTracker &progress_tracker; + NXFileObject_ProgressiveDownloader &parent; + + nx_uri_t temp_filename, url; + FILE *progressive_file_write; + jnl_http_t http; + char *user_agent; + nx_thread_t download_thread; + nu::MessageLoop message_loop; + uint64_t file_size; + int killswitch; +}; + +class NXFileObject_ProgressiveDownloader: public NXFileObject +{ +public: + NXFileObject_ProgressiveDownloader(); + ~NXFileObject_ProgressiveDownloader(); + ns_error_t Initialize(nx_uri_t uri, jnl_http_t http, const char *user_agent); + + bool Available(uint64_t size, uint64_t *available); + + /* API used by ProgressiveDownload */ + void OnFileSize(uint64_t filesize); + void OnConnected(); + void OnError(int error_code); + void OnClosed(); +private: + /* NXFileObject implementation */ + ns_error_t Read(void *buffer, size_t bytes_requested, size_t *bytes_read); + ns_error_t Write(const void *buffer, size_t bytes); + ns_error_t Seek(uint64_t position); + ns_error_t Tell(uint64_t *position); + ns_error_t PeekByte(uint8_t *byte); + ns_error_t Sync(); + ns_error_t Truncate(); + + bool WaitForRead(uint64_t size); + void ProcessMessage(nu::message_node_t *message); + void Wait(unsigned int milliseconds); + + ProgressiveDownload download; + ProgressTracker progress_tracker; + FILE *progressive_file_read; + bool end_of_file; + bool connected; + int error_code; + nu::MessageLoop message_loop; + bool closed; + bool need_seek; // if set to true, we need to fseek(position) +}; + +ProgressiveDownload::ProgressiveDownload(ProgressTracker &progress_tracker, NXFileObject_ProgressiveDownloader &parent) : progress_tracker(progress_tracker), parent(parent) +{ + killswitch=0; + url=0; + temp_filename=0; + progressive_file_write=0; + http=0; + user_agent=0; + download_thread=0; + file_size=0; +} + +ProgressiveDownload::~ProgressiveDownload() +{ + if (download_thread) + { + Close(); + NXThreadJoin(download_thread, 0); + } + + // TODO: flush messages + if (progressive_file_write) + fclose(progressive_file_write); + NXURIRelease(temp_filename); + NXURIRelease(url); + if (http) + jnl_http_release(http); + free(user_agent); +} + +void ProgressiveDownload::Close() +{ + nu::message_node_t *message = message_loop.AllocateMessage(); + message->message = MESSAGE_KILL; + message_loop.PostMessage(message); +} + +void ProgressiveDownload::Seek(uint64_t start, uint64_t end) +{ + seek_message_t *message = (seek_message_t *)message_loop.AllocateMessage(); + message->message = MESSAGE_SEEK; + message->start = start; + message->end = end; + message_loop.PostMessage(message); +} + +ns_error_t ProgressiveDownload::Initialize(nx_uri_t url, jnl_http_t http, const char *user_agent, nx_uri_t temp_filename) +{ + this->url = NXURIRetain(url); + this->temp_filename = NXURIRetain(temp_filename); + if (user_agent) + this->user_agent = strdup(user_agent); + this->http = jnl_http_retain(http); + progressive_file_write = NXFile_fopen(temp_filename, nx_file_FILE_readwrite_binary); + if (progressive_file_write == 0) + return NErr_FailedCreate; + + return NXThreadCreate(&download_thread, _ProgressiveThread, this); +} + +void ProgressiveDownload::ProcessMessage(nu::message_node_t *message) +{ + switch(message->message) + { + case MESSAGE_KILL: + killswitch=1; + break; + case MESSAGE_SEEK: + { + seek_message_t *seek_message = (seek_message_t *)message; + + char buffer[HTTP_BUFFER_SIZE] = {0}; + + /* empty out the jnetlib buffer. that might let us be able to avoid this seek */ + DoRead(buffer, sizeof(buffer)); + + uint64_t new_start, new_end; + if (!progress_tracker.Valid(seek_message->start, seek_message->end) /* double check that we actually need to seek */ + && !progress_tracker.Seek(seek_message->start, seek_message->end, &new_start, &new_end)) + { + int ret = SetupConnection(new_start, new_end); + if (ret == NErr_Success) + ret = Connect(); + if (ret != NErr_Success) + { + parent.OnError(ret); + killswitch=1; + break; + } + + _fseeki64(progressive_file_write, new_start, SEEK_SET); + } + else + parent.OnConnected(); + } + break; + } + + message_loop.FreeMessage(message); +} + +int ProgressiveDownload::Wait(int milliseconds) +{ + for (;;) + { + if (killswitch) + return 1; + + nu::message_node_t *message = message_loop.PeekMessage(milliseconds); + if (message) + ProcessMessage(message); + else + break; + } + + nu::message_node_t *message = message_loop.PeekMessage(milliseconds); + if (message) + ProcessMessage(message); + + return killswitch; +} + +ns_error_t ProgressiveDownload::SetupConnection(uint64_t start_position, uint64_t end_position) +{ + if (!http) + http = jnl_http_create(HTTP_BUFFER_SIZE, 0); + + if (!http) + return NErr_FailedCreate; + + jnl_http_reset_headers(http); + if (user_agent) + jnl_http_addheadervalue(http, "User-Agent", user_agent); + + if (start_position && start_position != (uint64_t)-1) + { + if (end_position == (uint64_t)-1) + { + char temp[128] = {0}; + sprintf(temp, "Range: bytes=%llu-", start_position); + jnl_http_addheader(http, temp); + } + else + { + char temp[128] = {0}; + sprintf(temp, "Range: bytes=%llu-%llu", start_position, end_position); + jnl_http_addheader(http, temp); + } + } + + jnl_http_addheader(http, "Connection: Close"); // TODO: change if we ever want a persistent connection and downloading in chunks + jnl_http_connect(http, AutoCharUTF8(url), 1, "GET"); + + return NErr_Success; +} + +int ProgressiveDownload::Connect() +{ + // TODO: configurable timeout + /* wait for connection */ +#ifdef _DEBUG + const int timeout = 15000; +#else + const int timeout = 15; +#endif + time_t start_time = time(0); + + int http_status = jnl_http_get_status(http); + while (http_status == HTTPGET_STATUS_CONNECTING || http_status == HTTPGET_STATUS_READING_HEADERS) + { + if (Wait(55) != 0) + return NErr_Interrupted; + + int ret = jnl_http_run(http); + if (ret == HTTPGET_RUN_ERROR) + return NErr_ConnectionFailed; + if (start_time + timeout < time(0)) + return NErr_TimedOut; + + http_status = jnl_http_get_status(http); + } + + if (http_status == HTTPGET_STATUS_ERROR) + { + switch(jnl_http_getreplycode(http)) + { + case 400: + return NErr_BadRequest; + case 401: + // TODO: deal with this specially + return NErr_Unauthorized; + case 403: + // TODO: deal with this specially? + return NErr_Forbidden; + case 404: + return NErr_NotFound; + case 405: + return NErr_BadMethod; + case 406: + return NErr_NotAcceptable; + case 407: + // TODO: deal with this specially + return NErr_ProxyAuthenticationRequired; + case 408: + return NErr_RequestTimeout; + case 409: + return NErr_Conflict; + case 410: + return NErr_Gone; + case 500: + return NErr_InternalServerError; + case 503: + return NErr_ServiceUnavailable; + default: + return NErr_ConnectionFailed; + } + } + else + { + if (!file_size) + { + // TODO: check range header for actual size + file_size = jnl_http_content_length(http); + parent.OnFileSize(file_size); + } + parent.OnConnected(); + return NErr_Success; + } +} + +void ProgressiveDownload::Internal_Write(const void *data, size_t data_len) +{ + size_t bytes_written = fwrite(data, 1, data_len, progressive_file_write); + fflush(progressive_file_write); + progress_tracker.Write(bytes_written); +} + +int ProgressiveDownload::DoRead(void *buffer, size_t bufferlen) +{ + int ret = jnl_http_run(http); + size_t bytes_received; + do + { + ret = jnl_http_run(http); + bytes_received = jnl_http_get_bytes(http, buffer, bufferlen); + if (bytes_received) + { + Internal_Write(buffer, bytes_received); + } + /* TODO: benski> should we limit the number of times through this loop? + I'm worried that if data comes in fast enough we might get stuck in this for a long time */ + } while (bytes_received == bufferlen); + return ret; +} + +nx_thread_return_t ProgressiveDownload::ProgressiveThread() +{ + ns_error_t ret; + + if (!http) + { + ret = SetupConnection(0, (uint64_t)-1); + if (ret != NErr_Success) + { + parent.OnError(ret); + parent.OnClosed(); + return 0; + } + } + + + ret = Connect(); + if (ret != NErr_Success) + { + parent.OnError(ret); + } + else + { + for (;;) + { + if (Wait(10) == 1) + break; // killed! + + char buffer[HTTP_BUFFER_SIZE] = {0}; + int ret = DoRead(buffer, sizeof(buffer)); + if (ret == -1) + break; + else if (ret == HTTPGET_RUN_CONNECTION_CLOSED) + { + if (jnl_http_bytes_available(http) == 0) + { + if (progress_tracker.Valid(0, file_size)) + { + // file is completely downloaded. let's gtfo + fclose(progressive_file_write); + progressive_file_write=0; + break; + } + + // if we're not completely full then we need to sit around for a potential MESSAGE_SEEK + //while (Wait(100) == 0) + { + // nop + } + } + } + } + } + + parent.OnClosed(); + return 0; +} + + /* ------------------ */ +NXFileObject_ProgressiveDownloader::NXFileObject_ProgressiveDownloader() : download(progress_tracker, *this) +{ + progressive_file_read=0; + end_of_file=false; + connected=false; + error_code=NErr_Success; + closed = false; + need_seek=false; + position=0; +} + + + +NXFileObject_ProgressiveDownloader::~NXFileObject_ProgressiveDownloader() +{ + download.Close(); + while (!closed) + Wait(10); + if (progressive_file_read) + fclose(progressive_file_read); +} + +void NXFileObject_ProgressiveDownloader::OnConnected() +{ + nu::message_node_t *message = message_loop.AllocateMessage(); + message->message = MESSAGE_CONNECTED; + message_loop.PostMessage(message); +} + +void NXFileObject_ProgressiveDownloader::OnError(int error_code) +{ + error_message_t *message = (error_message_t *)message_loop.AllocateMessage(); + message->message = MESSAGE_ERROR; + message->error_code = error_code; + message_loop.PostMessage(message); +} + +void NXFileObject_ProgressiveDownloader::OnFileSize(uint64_t size) +{ + size_message_t *message = (size_message_t *)message_loop.AllocateMessage(); + message->message = MESSAGE_SIZE; + message->size = size; + message_loop.PostMessage(message); +} + +void NXFileObject_ProgressiveDownloader::OnClosed() +{ + nu::message_node_t *message = message_loop.AllocateMessage(); + message->message = MESSAGE_CLOSED; + message_loop.PostMessage(message); +} + +ns_error_t NXFileObject_ProgressiveDownloader::Initialize(nx_uri_t uri, jnl_http_t http, const char *user_agent) +{ + ReferenceCountedNXURI temp_uri; + NXURICreateTemp(&temp_uri); + ns_error_t ret = download.Initialize(uri, http, user_agent, temp_uri); + if (ret != NErr_Success) + { + closed=true; + return ret; + } + + progressive_file_read = NXFile_fopen(temp_uri, nx_file_FILE_read_binary); + + for (;;) + { + Wait(10); + if (error_code != NErr_Success) + return error_code; + + if (connected) + break; + } + return NErr_Success; +} + +void NXFileObject_ProgressiveDownloader::ProcessMessage(nu::message_node_t *message) +{ + switch(message->message) + { + case MESSAGE_ERROR: + { + error_message_t *seek_message = (error_message_t *)message; + error_code = seek_message->error_code; + } + break; + case MESSAGE_CONNECTED: + connected = true; + break; + case MESSAGE_SIZE: + { + size_message_t *seek_message = (size_message_t *)message; + region.end = seek_message->size; + } + break; + case MESSAGE_CLOSED: + closed=true; + break; + } + + message_loop.FreeMessage(message); +} + +void NXFileObject_ProgressiveDownloader::Wait(unsigned int milliseconds) +{ + for (;;) + { + nu::message_node_t *message = message_loop.PeekMessage(milliseconds); + if (message) + ProcessMessage(message); + else + break; + } + + nu::message_node_t *message = message_loop.PeekMessage(milliseconds); + if (message) + ProcessMessage(message); +} + +bool NXFileObject_ProgressiveDownloader::WaitForRead(uint64_t size) +{ + if (progress_tracker.Valid(position, position+size)) + return true; + + if (need_seek) + { + // give it just a little bit of time to avoid constant reseeks when the download thread is just barely keeping up + Wait(10); + if (progress_tracker.Valid(position, position+size)) + return true; + + connected=false; + error_code=NErr_Success; + download.Seek(position, (uint64_t)position+size); + + for (;;) + { + Wait(10); + if (error_code != NErr_Success) + return false; + + if (connected) + break; + } + } + + while (!progress_tracker.Valid(position, position+size)) + { + Wait(10); + } + + return true; +} + + +ns_error_t NXFileObject_ProgressiveDownloader::Read(void *buffer, size_t bytes_requested, size_t *bytes_read) +{ + if (end_of_file || position >= (region.end - region.start)) + return NErr_EndOfFile; + + // don't allow a read past the end of the file as this will confuse progress_tracker (which doesn't know/care about the file length) + if ((position + bytes_requested) > region.end) + bytes_requested = (size_t)(region.end - position); + + if (WaitForRead((uint64_t)bytes_requested) == false) + { + *bytes_read = 0; + return error_code; + } + + if (need_seek) + { + _fseeki64(progressive_file_read, position, SEEK_SET); + need_seek=false; + } + + /* TODO: benski> if r < bytes_requested, then we need to flush the buffer. + on windows, we can use fflush(progressive_file_read) + on other platforms it's not guaranteed! */ + size_t r = fread(buffer, 1, bytes_requested, progressive_file_read); + this->position += r; + *bytes_read = r; + return NErr_Success; +} + +ns_error_t NXFileObject_ProgressiveDownloader::Seek(uint64_t new_position) +{ + if (new_position >= (region.end - region.start)) + { + this->position = region.end - region.start; + end_of_file=true; + } + else + { + if (new_position == position) + return NErr_Success; + position = new_position; + need_seek=true; + + end_of_file=false; + } + return NErr_Success; +} + +ns_error_t NXFileObject_ProgressiveDownloader::Tell(uint64_t *position) +{ + if (end_of_file) + *position = region.end - region.start; + else + *position = this->position - region.start; + return NErr_Success; +} + +ns_error_t NXFileObject_ProgressiveDownloader::PeekByte(uint8_t *byte) +{ + if (position == region.end) + return NErr_EndOfFile; + + // make sure we have enough room + if (WaitForRead((uint64_t)1) == false) + return error_code; + + if (need_seek) + { + _fseeki64(progressive_file_read, position, SEEK_SET); + need_seek=false; + } + + int read_byte = fgetc(progressive_file_read); + if (read_byte != EOF) + ungetc(read_byte, progressive_file_read); + else + { + /* TODO: benski> if we hit the point, then we actually need to flush the buffer. + on some platforms, fflush(progressive_file_read) will do that, but it's not guaranteed! */ + return NErr_EndOfFile; + } + + *byte = (uint8_t)read_byte; + return NErr_Success; +} + +ns_error_t NXFileObject_ProgressiveDownloader::Sync() +{ + return NErr_NotImplemented; +} + +ns_error_t NXFileObject_ProgressiveDownloader::Truncate() +{ + return NErr_NotImplemented; +} + +ns_error_t NXFileObject_ProgressiveDownloader::Write(const void *buffer, size_t bytes) +{ + return NErr_NotImplemented; +} + +bool NXFileObject_ProgressiveDownloader::Available(uint64_t size, uint64_t *available) +{ + uint64_t end = position+size; + if (end > region.end) + end = region.end; + if (position == region.end) + { + if (available) + *available=0; + return true; + } + return progress_tracker.Valid(position, end, available); +} + +ns_error_t NXFileOpenProgressiveDownloader(nx_file_t *out_file, nx_uri_t filename, nx_file_FILE_flags_t flags, jnl_http_t http, const char *user_agent) +{ + NXFileObject_ProgressiveDownloader *file_object = new (std::nothrow) NXFileObject_ProgressiveDownloader; + if (!file_object) + return NErr_OutOfMemory; + + ns_error_t ret = file_object->Initialize(filename, http, user_agent); + if (ret != NErr_Success) + { + delete file_object; + return ret; + } + + *out_file = (nx_file_t)file_object; + return NErr_Success; +} + +ns_error_t NXFileProgressiveDownloaderAvailable(nx_file_t _f, uint64_t size, uint64_t *available) +{ + if (!_f) + return NErr_BadParameter; + + NXFileObject_ProgressiveDownloader *f = (NXFileObject_ProgressiveDownloader *)_f; + if (f->Available(size, available)) + return NErr_True; + else + return NErr_False; +}
\ No newline at end of file diff --git a/Src/replicant/nx/win/NXZipFile.cpp b/Src/replicant/nx/win/NXZipFile.cpp new file mode 100644 index 00000000..71b00a51 --- /dev/null +++ b/Src/replicant/nx/win/NXZipFile.cpp @@ -0,0 +1,209 @@ +#include "NXFileObject.h" +#include <new> +#include "minizip/unzip.h" +#include <nx/nxfile.h> +#include <assert.h> + +class NXZipFile : NXFileObject +{ +public: + NXZipFile(unzFile zip_file); + ~NXZipFile(); + + /* NXFileObject implementation */ + ns_error_t Read(void *buffer, size_t bytes_requested, size_t *bytes_read); + ns_error_t Write(const void *buffer, size_t bytes); + ns_error_t Seek(uint64_t position); + ns_error_t Tell(uint64_t *position); + ns_error_t PeekByte(uint8_t *byte); + ns_error_t Sync(); + ns_error_t Truncate(); + // TODO(benski) implementation EOF + // TODO(benski) implement region locking +private: + unzFile zip_file; +}; + +NXZipFile::NXZipFile(unzFile zip_file) : zip_file(zip_file) +{ +} + +NXZipFile::~NXZipFile() +{ + if (zip_file) { + unzCloseCurrentFile(zip_file); + unzClose(zip_file); + zip_file=0; + } +} + +/* NXFileObject implementation */ +ns_error_t NXZipFile::Read(void *buffer, size_t bytes_requested, size_t *bytes_read) +{ + int zret = unzReadCurrentFile(zip_file, buffer, (unsigned int)bytes_requested); + if (zret == 0) { + if (bytes_read) { + *bytes_read = 0; + } + return NErr_EndOfFile; + } else if (zret > 0) { + if (bytes_read) { + *bytes_read = (size_t)zret; + } + return NErr_Success; + } else { + if (bytes_read) { + *bytes_read = 0; + } + return NErr_Error; + } +} + +ns_error_t NXZipFile::Write(const void *buffer, size_t bytes) +{ + return NErr_NotImplemented; +} + +ns_error_t NXZipFile::Seek(uint64_t position) +{ + // TODO(benski) error check) + unzSetOffset64(zip_file, position); + return NErr_Success; +} + +ns_error_t NXZipFile::Tell(uint64_t *position) +{ + *position = unzGetOffset64(zip_file); + return NErr_Success; +} + +ns_error_t NXZipFile::PeekByte(uint8_t *byte) +{ + return NErr_NotImplemented; +} + +ns_error_t NXZipFile::Sync() +{ + return NErr_NotImplemented; +} + +ns_error_t NXZipFile::Truncate() +{ + return NErr_NotImplemented; +} + +static voidpf ZCALLBACK unzip_nxfile_open OF((voidpf opaque, const void* filename, int mode)) +{ + nx_file_t f; + if (NXFileOpenFile(&f, (nx_uri_t)filename, nx_file_FILE_read_binary) != NErr_Success) { + return 0; + } + return f; +} + +static uLong ZCALLBACK unzip_nxfile_read OF((voidpf opaque, voidpf stream, void* buf, uLong size)) +{ + nx_file_t f = (nx_file_t)stream; + size_t bytes_read; + if (NXFileRead(f, buf, size, &bytes_read) != NErr_Success) { + return 0; + } + return (uLong)bytes_read; +} + +static int ZCALLBACK unzip_nxfile_close OF((voidpf opaque, voidpf stream)) +{ + NXFileRelease((nx_file_t)stream); + return 0; +} + + +static ZPOS64_T ZCALLBACK unzip_nxfile_tell OF((voidpf opaque, voidpf stream)) +{ + nx_file_t f = (nx_file_t)stream; + uint64_t position; + if (NXFileTell(f, &position) == NErr_Success) { + return (int64_t)position; + } else { + return -1; + } +} + +static long ZCALLBACK unzip_nxfile_seek OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int whence)) +{ + nx_file_t f = (nx_file_t)stream; + uint64_t position; + if (whence == SEEK_SET) { + position = offset; + } else if (whence == SEEK_CUR) { + ns_error_t err = NXFileTell(f, &position); + if (err != NErr_Success) { + return -1; + } + position += offset; + } else if (whence == SEEK_END) { + uint64_t length; + NXFileLength(f, &length); + position = length + offset; + } else { + return -1; + } + ns_error_t err = NXFileSeek(f, position); + if (err == NErr_Success) { + return 0; + } else { + return -1; + } +} +#if 0 + open64_file_func zopen64_file; + read_file_func zread_file; + write_file_func zwrite_file; + tell64_file_func ztell64_file; + seek64_file_func zseek64_file; + close_file_func zclose_file; + testerror_file_func zerror_file; +#endif + +ns_error_t NXFileOpenZip(nx_file_t *out_file, nx_uri_t filename, nx_string_t extension_hint) +{ +#if 0 + typedef struct zlib_filefunc_def_s +{ + open_file_func zopen_file; + read_file_func zread_file; + write_file_func zwrite_file; + tell_file_func ztell_file; + seek_file_func zseek_file; + close_file_func zclose_file; + testerror_file_func zerror_file; + voidpf opaque; +} zlib_filefunc_def; +#endif + + zlib_filefunc64_def file_func = {0, }; + file_func.zopen64_file = unzip_nxfile_open; + file_func.zread_file = unzip_nxfile_read; + file_func.ztell64_file = unzip_nxfile_tell; + file_func.zseek64_file = unzip_nxfile_seek; + file_func.zclose_file = unzip_nxfile_close; + + unzFile zip_file = unzOpen2_64(filename, &file_func); + if (zip_file == NULL) { + return NErr_Error; + } + + unzGoToFirstFile(zip_file); + // TODO(benski): look for filename with extension_hint as extension + // TODO(benski): search for anything with extension + unzOpenCurrentFile(zip_file); + + NXZipFile *nx_zip_file = new (std::nothrow) NXZipFile(zip_file); + if (!nx_zip_file) { + unzCloseCurrentFile(zip_file); + unzClose(zip_file); + return NErr_OutOfMemory; + } + *out_file = (nx_file_t)nx_zip_file; + return NErr_Success; +} diff --git a/Src/replicant/nx/win/nxapi.h b/Src/replicant/nx/win/nxapi.h new file mode 100644 index 00000000..be8bf2ec --- /dev/null +++ b/Src/replicant/nx/win/nxapi.h @@ -0,0 +1,15 @@ +#pragma once +#include "../../foundation/guid.h" + +#ifdef NX_EXPORTS +#define NX_API __declspec(dllexport) +#else +#define NX_API __declspec(dllimport) +#endif + +/* increment this any time that the NX API changes in a non-backwards-compatible way (preferably rarely) */ +static const int nx_api_version = 1; + +// {E7079A4B-BBB3-441F-ADCD-E0F1FE276EE3} +static const GUID nx_platform_guid = +{ 0xe7079a4b, 0xbbb3, 0x441f, { 0xad, 0xcd, 0xe0, 0xf1, 0xfe, 0x27, 0x6e, 0xe3 } }; diff --git a/Src/replicant/nx/win/nxcondition.c b/Src/replicant/nx/win/nxcondition.c new file mode 100644 index 00000000..1e3ef009 --- /dev/null +++ b/Src/replicant/nx/win/nxcondition.c @@ -0,0 +1,66 @@ +#include "nxcondition.h" +#include "foundation/error.h" + +int NXConditionInitialize(nx_condition_t condition) +{ + if (condition == 0) + return NErr_NullPointer; + + InitializeCriticalSection(&condition->mutex); + InitializeConditionVariable(&condition->condition); + return NErr_Success; +} + +int NXConditionDestroy(nx_condition_t condition) +{ + if (condition == 0) + return NErr_NullPointer; + + DeleteCriticalSection(&condition->mutex); + return NErr_Success; +} + +int NXConditionLock(nx_condition_t condition) +{ + if (condition == 0) + return NErr_NullPointer; + + EnterCriticalSection(&condition->mutex); + return NErr_Success; +} + +int NXConditionUnlock(nx_condition_t condition) +{ +if (condition == 0) + return NErr_NullPointer; + + LeaveCriticalSection(&condition->mutex); + return NErr_Success; +} + +int NXConditionWait(nx_condition_t condition) +{ + if (condition == 0) + return NErr_NullPointer; + + SleepConditionVariableCS(&condition->condition, &condition->mutex, INFINITE); + return NErr_Success; +} + +int NXConditionTimedWait(nx_condition_t condition, unsigned int milliseconds) +{ + if (condition == 0) + return NErr_NullPointer; + + SleepConditionVariableCS(&condition->condition, &condition->mutex, milliseconds); + return NErr_Success; +} + +int NXConditionSignal(nx_condition_t condition) +{ + if (condition == 0) + return NErr_NullPointer; + + WakeConditionVariable(&condition->condition); + return NErr_Success; +}
\ No newline at end of file diff --git a/Src/replicant/nx/win/nxcondition.h b/Src/replicant/nx/win/nxcondition.h new file mode 100644 index 00000000..42a634aa --- /dev/null +++ b/Src/replicant/nx/win/nxcondition.h @@ -0,0 +1,28 @@ +#pragma once +#include "nx/nxapi.h" +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include <windows.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct nx_condition_struct_t +{ + CONDITION_VARIABLE condition; + CRITICAL_SECTION mutex; +} nx_condition_value_t, *nx_condition_t; + +NX_API int NXConditionInitialize(nx_condition_t condition); +NX_API int NXConditionDestroy(nx_condition_t condition); +NX_API int NXConditionLock(nx_condition_t condition); +NX_API int NXConditionUnlock(nx_condition_t condition); +NX_API int NXConditionWait(nx_condition_t condition); +NX_API int NXConditionTimedWait(nx_condition_t condition, unsigned int milliseconds); +NX_API int NXConditionSignal(nx_condition_t condition); + +#ifdef __cplusplus +} +#endif
\ No newline at end of file diff --git a/Src/replicant/nx/win/nxdata.c b/Src/replicant/nx/win/nxdata.c new file mode 100644 index 00000000..065eddbe --- /dev/null +++ b/Src/replicant/nx/win/nxdata.c @@ -0,0 +1,276 @@ +#include "nx/nxdata.h" +#include "foundation/atomics.h" +#include "foundation/error.h" +#include "nx/nxfile.h" +#include <sys/stat.h> + +/* windows implementation */ +struct nx_data_struct_t +{ + volatile size_t ref_count; + nx_string_t mime_type; + nx_string_t description; + nx_uri_t source_uri; + nx_file_stat_t source_stats; + size_t len; + uint8_t data[1]; +}; + +static size_t NXDataMallocSize(size_t bytes) +{ + /* TODO: overflow check? */ + const nx_data_t dummy=0; + size_t header = (size_t)&dummy->data[0] - (size_t)dummy; + return header + bytes; +} + +nx_data_t NXDataRetain(nx_data_t data) +{ + if (!data) + return 0; + + nx_atomic_inc(&data->ref_count); + return data; +} + +void NXDataRelease(nx_data_t data) +{ + if (data) + { + if (nx_atomic_dec(&data->ref_count) == 0) + { + free(data->source_stats); + NXURIRelease(data->source_uri); + NXStringRelease(data->mime_type); + NXStringRelease(data->description); + free(data); + } + } +} + +int NXDataCreate(nx_data_t *out_data, const void *bytes, size_t length) +{ + void *new_bytes; + int ret = NXDataCreateWithSize(out_data, &new_bytes, length); + if (ret != NErr_Success) + return ret; + + memcpy(new_bytes, bytes, length); + return NErr_Success; +} + +int NXDataCreateWithSize(nx_data_t *out_data, void **bytes, size_t length) +{ + nx_data_t data = 0; + size_t data_length = NXDataMallocSize(length); + data = (nx_data_t)malloc(data_length); + if (!data) + return NErr_OutOfMemory; + + data->ref_count = 1; + data->len = length; + data->mime_type=0; + data->source_uri=0; + data->source_stats=0; + data->description=0; + if (bytes) + *bytes = data->data; + *out_data=data; + return NErr_Success; +} + +int NXDataCreateEmpty(nx_data_t *out_data) +{ + return NXDataCreateWithSize(out_data, 0, 0); +} + +int NXDataCreateFromURI(nx_data_t *out_data, nx_uri_t filename) +{ + nx_file_stat_s stat_buffer; + nx_data_t data; + size_t data_length; + size_t bytes_read; + uint64_t file_length; + void *bytes; + int ret; + int fd; + + + fd = NXFile_open(filename, nx_file_O_BINARY|nx_file_O_RDONLY); + if (fd == -1) + return NErr_FileNotFound; + + ret = NXFile_fstat(fd, &stat_buffer); + if (ret != NErr_Success) + { + close(fd); + return ret; + } + + file_length = stat_buffer.file_size; + + if (file_length > SIZE_MAX) + { + close(fd); + return NErr_IntegerOverflow; + } + + data_length = (size_t)file_length; + + ret = NXDataCreateWithSize(&data, &bytes, data_length); + if (ret != NErr_Success) + { + close(fd); + return ret; + } + + data->source_stats=(nx_file_stat_t)malloc(sizeof(nx_file_stat_s)); + if (!data->source_stats) + { + close(fd); + NXDataRelease(data); + return NErr_OutOfMemory; + } + + bytes_read = read(fd, bytes, (int)data_length); + close(fd); + if (bytes_read != data_length) + { + NXDataRelease(data); + return NErr_Error; + } + + *data->source_stats=stat_buffer; + data->source_uri=NXURIRetain(filename); + *out_data = data; + return NErr_Success; +} + +int NXDataGet(nx_data_t data, const void **bytes, size_t *length) +{ + if (!data) + return NErr_BadParameter; + + if (data->len == 0) + return NErr_Empty; + + *bytes = data->data; + *length = data->len; + return NErr_Success; +} + +size_t NXDataSize(nx_data_t data) +{ + if (!data) + return 0; + + return data->len; +} + +int NXDataSetMIME(nx_data_t data, nx_string_t mime_type) +{ + nx_string_t old; + if (!data) + return NErr_BadParameter; + + old = data->mime_type; + data->mime_type = NXStringRetain(mime_type); + NXStringRelease(old); + return NErr_Success; +} + +int NXDataSetDescription(nx_data_t data, nx_string_t description) +{ + nx_string_t old; + if (!data) + return NErr_BadParameter; + + old = data->description; + data->description = NXStringRetain(description); + NXStringRelease(old); + return NErr_Success; +} + +int NXDataSetSourceURI(nx_data_t data, nx_uri_t source_uri) +{ + nx_uri_t old; + if (!data) + return NErr_BadParameter; + + old = data->source_uri; + data->source_uri = NXURIRetain(source_uri); + NXURIRelease(old); + return NErr_Success; +} + +int NXDataSetSourceStat(nx_data_t data, nx_file_stat_t source_stats) +{ + nx_file_stat_t new_stats; + if (!data) + return NErr_BadParameter; + + if (source_stats) + { + new_stats=(nx_file_stat_t)malloc(sizeof(nx_file_stat_s)); + if (!new_stats) + return NErr_OutOfMemory; + + *new_stats = *source_stats; + free(data->source_stats); + data->source_stats=new_stats; + } + else + { + free(data->source_stats); + data->source_stats=0; + } + return NErr_Success; +} + +int NXDataGetMIME(nx_data_t data, nx_string_t *mime_type) +{ + if (!data) + return NErr_BadParameter; + + if (!data->mime_type) + return NErr_Empty; + + *mime_type = NXStringRetain(data->mime_type); + return NErr_Success; +} + +int NXDataGetDescription(nx_data_t data, nx_string_t *description) +{ + if (!data) + return NErr_BadParameter; + + if (!data->description) + return NErr_Empty; + + *description = NXStringRetain(data->description); + return NErr_Success; +} + +int NXDataGetSourceURI(nx_data_t data, nx_uri_t *source_uri) +{ + if (!data) + return NErr_BadParameter; + + if (!data->source_uri) + return NErr_Empty; + + *source_uri = NXURIRetain(data->source_uri); + return NErr_Success; +} + +int NXDataGetSourceStat(nx_data_t data, nx_file_stat_t *source_stats) +{ + if (!data) + return NErr_BadParameter; + + if (!data->source_stats) + return NErr_Empty; + + *source_stats = data->source_stats; + return NErr_Success; +} diff --git a/Src/replicant/nx/win/nxdata.h b/Src/replicant/nx/win/nxdata.h new file mode 100644 index 00000000..1a5eee94 --- /dev/null +++ b/Src/replicant/nx/win/nxdata.h @@ -0,0 +1,42 @@ +#pragma once +#include "../../foundation/types.h" +#include "../../nx/nxuri.h" +#include "../../nx/nxapi.h" +#include "../../nx/nxfile.h" +#include "../../nx/nxstring.h" + +/* windows implementation */ +#ifdef __cplusplus +extern "C" { +#endif + typedef struct nx_data_struct_t *nx_data_t; + + NX_API nx_data_t NXDataRetain(nx_data_t data); + NX_API void NXDataRelease(nx_data_t data); + + NX_API int NXDataCreate(nx_data_t *data, const void *bytes, size_t length); + NX_API int NXDataCreateWithSize(nx_data_t *data, void **bytes, size_t length); + /* creates an empty data object. useful if you need to store MIME, source URI, etc. without having actual data */ + NX_API int NXDataCreateEmpty(nx_data_t *data); + /* you can pass file_stats==NULL if you don't care about the file stats */ + NX_API int NXDataCreateFromURI(nx_data_t *data, nx_uri_t filename); + + NX_API size_t NXDataSize(nx_data_t data); + NX_API int NXDataGet(nx_data_t data, const void **bytes, size_t *length); + + /* You can _only_ call these on your own nx_data_t object _before_ you give it to anyone else! */ + NX_API int NXDataSetMIME(nx_data_t data, nx_string_t mime_type); + NX_API int NXDataSetDescription(nx_data_t data, nx_string_t description); + NX_API int NXDataSetSourceURI(nx_data_t data, nx_uri_t source_uri); + NX_API int NXDataSetSourceStat(nx_data_t data, nx_file_stat_t source_stats); + + /* you need to call NXStringRelease on what you get back (if the function succeeded) */ + NX_API int NXDataGetMIME(nx_data_t data, nx_string_t *mime_type); + NX_API int NXDataGetDescription(nx_data_t data, nx_string_t *description); + NX_API int NXDataGetSourceURI(nx_data_t data, nx_uri_t *source_uri); + NX_API int NXDataGetSourceStat(nx_data_t data, nx_file_stat_t *source_stats); + + +#ifdef __cplusplus +} +#endif diff --git a/Src/replicant/nx/win/nxfile.c b/Src/replicant/nx/win/nxfile.c new file mode 100644 index 00000000..dbf79089 --- /dev/null +++ b/Src/replicant/nx/win/nxfile.c @@ -0,0 +1,68 @@ +#include "nxfile.h" +#include "foundation/error.h" +#include <sys/stat.h> +ns_error_t NXFile_move(nx_uri_t destination, nx_uri_t source) +{ + if (!ReplaceFile(destination->string, source->string, 0, 0, 0, 0)) + { + if (!MoveFile(source->string, destination->string)) + { + if (!CopyFile(source->string, destination->string, FALSE)) + { + return NErr_Error; + } + DeleteFile(source->string); + } + } + return NErr_Success; +} + +ns_error_t NXFile_unlink(nx_uri_t filename) +{ + if (DeleteFile(filename->string)) + return NErr_Success; + else + return NErr_Error; +} + +ns_error_t NXFile_stat(nx_uri_t filename, nx_file_stat_t file_stats) +{ + struct __stat64 buffer; + + if (_wstat64(filename->string, &buffer) == 0) + { + file_stats->access_time = buffer.st_atime; + file_stats->creation_time = buffer.st_ctime; + file_stats->modified_time = buffer.st_mtime; + file_stats->file_size = buffer.st_size; + return NErr_Success; + } + else + return NErr_Error; +} + +ns_error_t NXFile_statFILE(FILE *f, nx_file_stat_t file_stats) +{ + int fd = _fileno(f); + if (fd == -1) + return NErr_Error; + + return NXFile_fstat(fd, file_stats); +} + +ns_error_t NXFile_fstat(int file_descriptor, nx_file_stat_t file_stats) +{ + struct __stat64 buffer; + + if (_fstat64(file_descriptor, &buffer) == 0) + { + file_stats->access_time = buffer.st_atime; + file_stats->creation_time = buffer.st_ctime; + file_stats->modified_time = buffer.st_mtime; + file_stats->file_size = buffer.st_size; + return NErr_Success; + } + else + return NErr_Error; +} + diff --git a/Src/replicant/nx/win/nxfile.h b/Src/replicant/nx/win/nxfile.h new file mode 100644 index 00000000..d7d943e2 --- /dev/null +++ b/Src/replicant/nx/win/nxfile.h @@ -0,0 +1,116 @@ +#pragma once +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include <windows.h> +#include "../../nx/nxapi.h" +#include <stdio.h> // for FILE + +#include "../../nx/nxuri.h" +#include <io.h> +#include <fcntl.h> +#include "../../nx/nxtime.h" +#include "../../foundation/error.h" +#include "../../jnetlib/jnetlib.h" + +#ifdef __cplusplus +extern "C" { +#endif + + typedef struct nx_file_stat_s + { + nx_time_unix_64_t creation_time; + nx_time_unix_64_t access_time; + nx_time_unix_64_t modified_time; + uint64_t file_size; + } nx_file_stat_s, *nx_file_stat_t; + + typedef enum + { + nx_file_FILE_none = 0, + nx_file_FILE_binary = (1 << 0), + nx_file_FILE_read_text= (1 << 1), + nx_file_FILE_read_binary=nx_file_FILE_read_text|nx_file_FILE_binary, + nx_file_FILE_write_text=(1 << 2), + nx_file_FILE_write_binary=nx_file_FILE_write_text|nx_file_FILE_binary, + nx_file_FILE_update_text=(1 << 3), + nx_file_FILE_update_binary=nx_file_FILE_update_text|nx_file_FILE_binary, + nx_file_FILE_readwrite_text=(1 << 4), + nx_file_FILE_readwrite_binary=nx_file_FILE_readwrite_text|nx_file_FILE_binary, + + nx_file_FILE_writable_mask = nx_file_FILE_write_text|nx_file_FILE_update_text|nx_file_FILE_readwrite_text, + } nx_file_FILE_flags_t; + + static const int nx_file_O_BINARY=_O_BINARY; + static const int nx_file_O_WRONLY=_O_WRONLY; + static const int nx_file_O_RDONLY=_O_RDONLY; + + static FILE *NXFile_fopen(nx_uri_t filename, nx_file_FILE_flags_t flags) + { + if (filename) + { + if (flags == nx_file_FILE_read_binary) + { + return _wfopen(filename->string, L"rb"); + } + else if (flags == nx_file_FILE_write_binary) + { + return _wfopen(filename->string, L"wb"); + } + else if (flags == nx_file_FILE_update_binary) + { + return _wfopen(filename->string, L"r+b"); + } + else if (flags == nx_file_FILE_readwrite_binary) + { + return _wfopen(filename->string, L"w+b"); + } + } + return 0; + } + + /* returns a file descriptor */ + static int NXFile_open(nx_uri_t filename, int flags) + { + return _wopen(filename->string, flags); + } + + NX_API ns_error_t NXFile_move(nx_uri_t destination, nx_uri_t source); + NX_API ns_error_t NXFile_unlink(nx_uri_t filename); + NX_API ns_error_t NXFile_stat(nx_uri_t filename, nx_file_stat_t file_stats); + NX_API ns_error_t NXFile_statFILE(FILE *f, nx_file_stat_t file_stats); + NX_API ns_error_t NXFile_fstat(int file_descriptor, nx_file_stat_t file_stats); + + /* --------------------------------------------------------------------------- */ + typedef struct nx_file_s { size_t dummy; } *nx_file_t; + NX_API ns_error_t NXFileOpenFile(nx_file_t *out_file, nx_uri_t filename, nx_file_FILE_flags_t flags); + NX_API ns_error_t NXFileOpenProgressiveDownloader(nx_file_t *out_file, nx_uri_t filename, nx_file_FILE_flags_t flags, jnl_http_t http, const char *user_agent); + NX_API ns_error_t NXFileOpenZip(nx_file_t *out_file, nx_uri_t filename, nx_string_t extension_hint); + NX_API nx_file_t NXFileRetain(nx_file_t f); + NX_API void NXFileRelease(nx_file_t f); + /* the implementation of this function will only return NErr_EndOfFile if 0 bytes were read. + when *bytes_read < bytes_requested, it's likely that the file is at the end, but it will still return NErr_Success + until the next call */ + NX_API ns_error_t NXFileRead(nx_file_t f, void *buffer, size_t bytes_requested, size_t *bytes_read); + NX_API ns_error_t NXFileWrite(nx_file_t f, const void *buffer, size_t bytes); + NX_API ns_error_t NXFileSeek(nx_file_t f, uint64_t position); + NX_API ns_error_t NXFileTell(nx_file_t f, uint64_t *position); + NX_API ns_error_t NXFileLockRegion(nx_file_t _f, uint64_t start_position, uint64_t end_position); + NX_API ns_error_t NXFileUnlockRegion(nx_file_t _f); + /* file_stats does _not_ take into account the current region */ + NX_API ns_error_t NXFileStat(nx_file_t f, nx_file_stat_t file_stats); + /* returns the length of the file given the current region */ + NX_API ns_error_t NXFileLength(nx_file_t f, uint64_t *length); + /* returns NErr_True, NErr_False, or possibly some error */ + NX_API ns_error_t NXFileEndOfFile(nx_file_t f); + /* this exists as a one-off for nsmp4. hopefully we can get rid of it */ + NX_API ns_error_t NXFilePeekByte(nx_file_t f, uint8_t *byte); + NX_API ns_error_t NXFileSync(nx_file_t f); + NX_API ns_error_t NXFileTruncate(nx_file_t f); + + /* only valid for Progressive Downloader objects */ + NX_API ns_error_t NXFileProgressiveDownloaderAvailable(nx_file_t f, uint64_t size, uint64_t *available); + +#ifdef __cplusplus +} +#endif
\ No newline at end of file diff --git a/Src/replicant/nx/win/nximage.c b/Src/replicant/nx/win/nximage.c new file mode 100644 index 00000000..46586002 --- /dev/null +++ b/Src/replicant/nx/win/nximage.c @@ -0,0 +1,34 @@ +#include "nximage.h" + +static HANDLE image_heap; +void NXImageSetHeap(HANDLE _image_heap) +{ + if (!image_heap) + image_heap = _image_heap; +} + +static size_t NXImageMallocSize(size_t bytes) +{ + return sizeof(nx_image_s) + bytes - sizeof(ARGB32); +} + +nx_image_t NXImageMalloc(uint32_t width, uint32_t height) +{ + size_t bytes; + nx_image_t img; + bytes = width*height*4; // TODO: overflow check + + img = (nx_image_t)malloc(NXImageMallocSize(bytes)); + img->ref_count = 1; + img->len = bytes; + img->width = width; + img->height = height; + return img; + +} + +nx_image_t NXImageRetain(nx_image_t image) +{ + image->ref_count++; + return image; +}
\ No newline at end of file diff --git a/Src/replicant/nx/win/nximage.h b/Src/replicant/nx/win/nximage.h new file mode 100644 index 00000000..eab587f1 --- /dev/null +++ b/Src/replicant/nx/win/nximage.h @@ -0,0 +1,24 @@ +#pragma once +#include "foundation/types.h" +#include "nxapi.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct nx_image +{ + size_t ref_count; + uint32_t width; + uint32_t height; + size_t len; + ARGB32 image[1]; +} nx_image_s, *nx_image_t; + +NX_API void NXImageSetHeap(HANDLE image_heap); +NX_API nx_image_t NXImageMalloc(uint32_t width, uint32_t height); +NX_API nx_image_t NXImageRetain(nx_image_t image); + +#ifdef __cplusplus +} +#endif
\ No newline at end of file diff --git a/Src/replicant/nx/win/nxlog.c b/Src/replicant/nx/win/nxlog.c new file mode 100644 index 00000000..7e8da01b --- /dev/null +++ b/Src/replicant/nx/win/nxlog.c @@ -0,0 +1,19 @@ +#include "nxlog.h" +#include <stdio.h> +#include <stdarg.h> +//#include <windows.h> + +static char *nx_log_tag = "libreplicant"; +#define MAX_FMT_SIZE 512 + +void NXLog(int priority, char *fmt, ...){ + + char formatted_string[MAX_FMT_SIZE]; + + va_list argptr; + va_start(argptr,fmt); + vsnprintf(formatted_string, MAX_FMT_SIZE, fmt, argptr); + va_end(argptr); + +// OutputDebugString(formatted_string); +} diff --git a/Src/replicant/nx/win/nxlog.h b/Src/replicant/nx/win/nxlog.h new file mode 100644 index 00000000..9e3a41ad --- /dev/null +++ b/Src/replicant/nx/win/nxlog.h @@ -0,0 +1,13 @@ +#pragma once +#include "foundation/types.h" +#include "nx/nxapi.h" + +#ifdef __cplusplus +extern "C" { +#endif + +NX_API void NXLog(int priority, char *fmt, ...); + +#ifdef __cplusplus +} +#endif diff --git a/Src/replicant/nx/win/nxmutablestring.c b/Src/replicant/nx/win/nxmutablestring.c new file mode 100644 index 00000000..1e11bdba --- /dev/null +++ b/Src/replicant/nx/win/nxmutablestring.c @@ -0,0 +1,40 @@ +#include "nxmutablestring.h" +#include "foundation/error.h" + +/* currently this is closely coupled with the nx_string_t implementation. beware! */ +extern HANDLE string_heap; + +void NXMutableStringDestroy(nx_mutable_string_t mutable_string) +{ + if (mutable_string) + { + if (mutable_string->nx_string_data) + NXStringRelease(mutable_string->nx_string_data); + HeapFree(string_heap, 0, mutable_string); + } +} + +nx_mutable_string_t NXMutableStringCreateFromXML(const nsxml_char_t *characters, size_t num_characters) +{ + nx_mutable_string_t mutable_string = (nx_mutable_string_t)HeapAlloc(string_heap, 0, sizeof(nx_mutable_string_struct_t)); + NXStringCreateWithBytes(&mutable_string->nx_string_data, characters, num_characters*2, nx_charset_utf16le); + mutable_string->allocation_length = num_characters; + return mutable_string; +} + +int NXMutableStringGrowFromXML(nx_mutable_string_t mutable_string, const nsxml_char_t *characters, size_t num_characters) +{ + if (mutable_string->nx_string_data->len + num_characters + 1 > mutable_string->allocation_length) + { + nx_string_t new_string = NXStringRealloc(mutable_string->nx_string_data, mutable_string->nx_string_data->len + num_characters + 1); + if (!new_string) + return NErr_OutOfMemory; + mutable_string->nx_string_data = new_string; + mutable_string->allocation_length = mutable_string->nx_string_data->len + num_characters + 1; + } + memcpy(mutable_string->nx_string_data->string + mutable_string->nx_string_data->len, characters, num_characters*sizeof(wchar_t)); + mutable_string->nx_string_data->len += num_characters; + mutable_string->nx_string_data->string[mutable_string->nx_string_data->len]=0; /* well null terminate */ + + return NErr_Success; +}
\ No newline at end of file diff --git a/Src/replicant/nx/win/nxmutablestring.h b/Src/replicant/nx/win/nxmutablestring.h new file mode 100644 index 00000000..49485582 --- /dev/null +++ b/Src/replicant/nx/win/nxmutablestring.h @@ -0,0 +1,24 @@ +#pragma once + +#include "foundation/types.h" +#include "nx/nxstring.h" +#include "nx/nxapi.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct nx_mutable_string_struct_t +{ + size_t allocation_length; + nx_string_t nx_string_data; +} nx_mutable_string_struct_t, *nx_mutable_string_t; + + +NX_API nx_mutable_string_t NXMutableStringCreateFromXML(const nsxml_char_t *characters, size_t num_characters); +NX_API void NXMutableStringDestroy(nx_mutable_string_t mutable_string); +NX_API int NXMutableStringGrowFromXML(nx_mutable_string_t mutable_string, const nsxml_char_t *characters, size_t num_characters); + +#ifdef __cplusplus +} +#endif
\ No newline at end of file diff --git a/Src/replicant/nx/win/nxonce.c b/Src/replicant/nx/win/nxonce.c new file mode 100644 index 00000000..293534f7 --- /dev/null +++ b/Src/replicant/nx/win/nxonce.c @@ -0,0 +1,43 @@ +#include "nxonce.h" +#include "foundation/error.h" +#if 0 && _WIN32_WINNT >= 0x600 + +void NXOnce(nx_once_t once, int (NX_ONCE_API *init_fn)(nx_once_t, void *, void **), void *param) +{ + InitOnceExecuteOnce(once, (PINIT_ONCE_FN)init_fn, param, 0); +} + +void NXOnceInit(nx_once_t once) +{ + InitOnceInitialize(once); +} +#else +/* this ONLY works because of the strict(ish) memory ordering of the AMD64/x86 processors. + Don't use this implementation for a processor that has loose memory ordering restriction (e.g. ARM, PowerPC) + see http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf + */ +void NXOnce(nx_once_t once, int (NX_ONCE_API *init_fn)(nx_once_t, void *, void **), void *param) +{ + if (once->status) + return; + + EnterCriticalSection(&once->critical_section); + if (once->status) + { + LeaveCriticalSection(&once->critical_section); + return; + } + + init_fn(once, param, 0); + // benski> not important for the x86, but on processors with weak memory-order on stores, once->status might set to 1 BEFORE all stores from init_fn complete! + once->status = 1; + LeaveCriticalSection(&once->critical_section); +} + +void NXOnceInit(nx_once_t once) +{ + once->status=0; + InitializeCriticalSection(&once->critical_section); +} + +#endif
\ No newline at end of file diff --git a/Src/replicant/nx/win/nxonce.h b/Src/replicant/nx/win/nxonce.h new file mode 100644 index 00000000..7cdd53a6 --- /dev/null +++ b/Src/replicant/nx/win/nxonce.h @@ -0,0 +1,35 @@ +#pragma once +#include "nxapi.h" +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include <windows.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#if 0 && _WIN32_WINNT >= 0x600 + typedef INIT_ONCE nx_once_value_t; + typedef INIT_ONCE *nx_once_t; +#define NX_ONCE_INITIALIZE INIT_ONCE_STATIC_INIT +#define NX_ONCE_API CALLBACK + +NX_API void NXOnce(nx_once_t once, int (NX_ONCE_API *init_fn)(nx_once_t, void *, void **), void *param); +NX_API void NXOnceInit(nx_once_t once); +#else + typedef struct nx_once_s + { + volatile int status; + CRITICAL_SECTION critical_section; + } nx_once_value_t, *nx_once_t; + +#define NX_ONCE_API + + NX_API void NXOnce(nx_once_t once, int (NX_ONCE_API *init_fn)(nx_once_t, void *, void **), void *); + NX_API void NXOnceInit(nx_once_t once); + +#endif +#ifdef __cplusplus +} +#endif
\ No newline at end of file diff --git a/Src/replicant/nx/win/nxpath.c b/Src/replicant/nx/win/nxpath.c new file mode 100644 index 00000000..1841640b --- /dev/null +++ b/Src/replicant/nx/win/nxpath.c @@ -0,0 +1,113 @@ +#include "nxpath.h" +#include <shlwapi.h> +#include "foundation/error.h" + +static const wchar_t *FindExtension(nx_uri_t filename) +{ + size_t position; + if (!filename || !filename->string || !filename->len) + return 0; + + position=filename->len; + while (position--) + { + wchar_t c = filename->string[position]; + if (c == '.') + return &filename->string[position+1]; + if (c == '/' || c == '\\') + return 0; + } + return 0; +} + +static const wchar_t *FindFilename(nx_uri_t filename) +{ + size_t position; + if (!filename || !filename->string || !filename->len) + return 0; + + position=filename->len; + while (position--) + { + wchar_t c = filename->string[position]; + if (c == '/' || c == '\\') + return &filename->string[position+1]; + } + return 0; +} + +size_t NXPathMatchExtensionList(nx_uri_t filename, nx_string_t *extension_list, size_t num_extensions) +{ + const wchar_t *ext = FindExtension(filename); + if (ext && *ext) + { + size_t i; + for (i=0;i<num_extensions;i++) + { +#if WINVER >= 0x0600 + if (CompareStringOrdinal(ext, -1, extension_list[i]->string, -1, TRUE) == CSTR_EQUAL) + return i; +#else + if (CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, ext, -1, extension_list[i]->string, -1) == CSTR_EQUAL) + return i; +#endif + } + } + return num_extensions; +} + +int NXPathMatchExtension(nx_uri_t filename, nx_string_t extension) +{ + const wchar_t *ext = FindExtension(filename); + if (ext && *ext) + { +#if WINVER >= 0x0600 + if (CompareStringOrdinal(ext, -1, extension->string, -1, TRUE) == CSTR_EQUAL) + return NErr_Success; +#else + if (CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, ext, -1, extension->string, -1) == CSTR_EQUAL) + return NErr_Success; +#endif + } + return NErr_False; +} + +int NXPathProtocol(nx_uri_t filename, const char *protocol) +{ + if (PathIsURL(filename->string)) + { + wchar_t protocol_from_filename[100]; + DWORD protocol_length=100; + if (UrlGetPart(filename->string, protocol_from_filename, &protocol_length, URL_PART_SCHEME, 0) == S_OK) + { + DWORD i; + for (i=0;i<protocol_length;i++) + { + if ((wchar_t)(protocol[i]) != protocol_from_filename[i]) + return NErr_False; + } + return NErr_Success; + } + } + return NErr_False; +} + +int NXPathIsURL(nx_uri_t filename) +{ + if (PathIsURL(filename->string)) + return NErr_True; + else + return NErr_False; +} + +int NXPathIsRelative(nx_uri_t filename) +{ + if (filename->len >= 3 && filename->string[1] == L':' && (filename->string[2] == L'\\' || filename->string[2] == L'/')) + return NErr_False; + + if (filename->len >= 1 && (filename->string[2] == L'\\' || filename->string[2] == L'/')) + return NErr_False; + + return NErr_True; +} + diff --git a/Src/replicant/nx/win/nxpath.h b/Src/replicant/nx/win/nxpath.h new file mode 100644 index 00000000..baf70d71 --- /dev/null +++ b/Src/replicant/nx/win/nxpath.h @@ -0,0 +1,26 @@ +#pragma once +#include "foundation/types.h" +#include "nx/nxapi.h" +#include "nx/nxstring.h" +#include "nx/nxuri.h" + +#ifdef __cplusplus +extern "C" { +#endif + + // returns index into the extension list of a match extension + // returns >= num_extensions on failure +NX_API size_t NXPathMatchExtensionList(nx_uri_t filename, nx_string_t *extension_list, size_t num_extensions); + +// return NErr_True / NErr_False +NX_API int NXPathMatchExtension(nx_uri_t filename, nx_string_t extension); + +// return NErr_True / NErr_False +NX_API int NXPathProtocol(nx_uri_t filename, const char *protocol); + +// return NErr_True / NErr_False +NX_API int NXPathIsURL(nx_uri_t filename); + +#ifdef __cplusplus +} +#endif
\ No newline at end of file diff --git a/Src/replicant/nx/win/nxsemaphore.c b/Src/replicant/nx/win/nxsemaphore.c new file mode 100644 index 00000000..25070336 --- /dev/null +++ b/Src/replicant/nx/win/nxsemaphore.c @@ -0,0 +1,24 @@ +#include "nxsemaphore.h" +#include "foundation/error.h" +int NXSemaphoreCreate(nx_semaphore_t *sem) +{ + *sem = CreateSemaphore(0, 0, LONG_MAX, 0); + return NErr_Success; +} + +int NXSemaphoreRelease(nx_semaphore_t sem) +{ + ReleaseSemaphore(sem, 1, 0); + return NErr_Success; +} + +int NXSemaphoreWait(nx_semaphore_t sem) +{ + WaitForSingleObject(sem, INFINITE); + return NErr_Success; +} + +void NXSemaphoreClose(nx_semaphore_t sem) +{ + CloseHandle(sem); +}
\ No newline at end of file diff --git a/Src/replicant/nx/win/nxsemaphore.h b/Src/replicant/nx/win/nxsemaphore.h new file mode 100644 index 00000000..9509fe5a --- /dev/null +++ b/Src/replicant/nx/win/nxsemaphore.h @@ -0,0 +1,16 @@ +#pragma once +#include <windows.h> +#include "nx/nxapi.h" + +#ifdef __cplusplus +extern "C" { +#endif + typedef HANDLE nx_semaphore_t; + + NX_API int NXSemaphoreCreate(nx_semaphore_t *sem); + NX_API int NXSemaphoreRelease(nx_semaphore_t sem); + NX_API int NXSemaphoreWait(nx_semaphore_t sem); + NX_API void NXSemaphoreClose(nx_semaphore_t sem); +#ifdef __cplusplus +} +#endif
\ No newline at end of file diff --git a/Src/replicant/nx/win/nxsleep.c b/Src/replicant/nx/win/nxsleep.c new file mode 100644 index 00000000..245cf4c8 --- /dev/null +++ b/Src/replicant/nx/win/nxsleep.c @@ -0,0 +1,14 @@ +#include "nxsleep.h" +#include "foundation/error.h" +int NXSleep(unsigned int milliseconds) +{ + Sleep(milliseconds); + return NErr_Success; +} + +int NXSleepYield(void) +{ + Sleep(0); + return NErr_Success; +} + diff --git a/Src/replicant/nx/win/nxsleep.h b/Src/replicant/nx/win/nxsleep.h new file mode 100644 index 00000000..98da22f0 --- /dev/null +++ b/Src/replicant/nx/win/nxsleep.h @@ -0,0 +1,17 @@ +#pragma once +#include "nx/nxapi.h" +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include <windows.h> + +#ifdef __cplusplus +extern "C" { +#endif + +NX_API int NXSleep(unsigned int milliseconds); +NX_API int NXSleepYield(void); + +#ifdef __cplusplus +} +#endif diff --git a/Src/replicant/nx/win/nxstring.c b/Src/replicant/nx/win/nxstring.c new file mode 100644 index 00000000..fca479e2 --- /dev/null +++ b/Src/replicant/nx/win/nxstring.c @@ -0,0 +1,756 @@ +#include "nxstring.h" +#include "foundation/error.h" +#include <shlwapi.h> +#include "foundation/atomics.h" +#include <wchar.h> +#include <stdarg.h> +#include <stdio.h> +#include <assert.h> +#pragma comment(lib, "shlwapi.lib") + +//#define NX_STRING_STRICT_HEAP + +HANDLE string_heap = 0; + +int NXStringSetHeap(HANDLE _string_heap) +{ + if (!string_heap) + { + string_heap = _string_heap; + return NErr_Success; + } + else + { + return NErr_NoAction; + } +} + +// don't include null terminator here +static size_t NXStringMallocSize(size_t characters) +{ + /* TODO: overflow check? */ + const nx_string_t dummy=NULL; + size_t header = (size_t)&dummy->string[0] - (size_t)dummy; + return header + (characters+1) * sizeof(wchar_t); +} + +// don't include null terminator here +nx_string_t NXStringMalloc(size_t characters) +{ + if (!string_heap) + { + string_heap = GetProcessHeap(); + } + return NXStringMallocWithHeap(string_heap, characters); +} + +nx_string_t NXStringRealloc(nx_string_t str, size_t characters) +{ + nx_string_t new_str = (nx_string_t)HeapReAlloc(string_heap, 0, str, NXStringMallocSize(characters)); + // on failure, kick back the original block (TODO need to review this) + if (!new_str) + { + return str; + } + return new_str; +} + +nx_string_t NXStringMallocWithHeap(HANDLE heap, size_t characters) +{ +#ifdef NX_STRING_STRICT_HEAP + nx_string_t str; + size_t string_size = NXStringMallocSize(characters); + + size_t allocated_size = (string_size + 8191) & ~4095; + size_t offset = 4096 - (string_size & 4095); + size_t pages = allocated_size / 4096; + uint8_t *protect_start; + void *mem = VirtualAlloc(0, allocated_size, MEM_COMMIT, PAGE_READWRITE); + + if (!mem) + return 0; + + protect_start = (uint8_t *)mem + (pages-1)*4096; + VirtualProtect(protect_start, 4096, PAGE_NOACCESS, 0); + + str = (nx_string_t)((uint8_t *)mem + offset); + str->ref_count = 1; + str->len = characters; + return str; +#else + nx_string_t str = (nx_string_t)HeapAlloc(heap, 0, NXStringMallocSize(characters)); + if (str) + { + str->ref_count = 1; + str->len = characters; + } + return str; +#endif +} + +int NXStringFree(HANDLE heap, nx_string_t str) +{ +#ifdef NX_STRING_STRICT_HEAP + uint8_t *mem = (uint8_t *)((size_t)str & 4095); + VirtualProtect(mem, 4096, PAGE_NOACCESS, 0); + assert(_heapchk() == _HEAPOK); + return NErr_Success; +#else + if (HeapFree(heap, 0, str)) + { + return NErr_Success; + } + else + { + return NErr_Error; + } +#endif +} + +nx_string_t NXStringCreate(const wchar_t *str) +{ + size_t size; + nx_string_t nxstr; + + if (!str || (size_t)str <= 65536) + { + return 0; + } + + size = wcslen(str); + nxstr = NXStringMalloc(size); + if (nxstr) + { + memcpy(nxstr->string, str, size*sizeof(wchar_t)); + nxstr->string[size]=0; + } + return nxstr; +} + +int NXStringCreateEmpty(nx_string_t *new_string) +{ + nx_string_t nxstr = NXStringMalloc(0); + if (nxstr) + { + nxstr->string[0]=0; + *new_string = nxstr; + return NErr_Success; + } + else + { + return NErr_OutOfMemory; + } +} + +nx_string_t NXStringCreateWithHeap(HANDLE heap, const wchar_t *str) +{ + size_t size = wcslen(str); + nx_string_t nxstr = NXStringMallocWithHeap(heap, size); + if (nxstr) + { + memcpy(nxstr->string, str, size*sizeof(wchar_t)); + nxstr->string[size]=0; + } + return nxstr; +} + +nx_string_t NXStringCreateFromUTF8(const char *str) +{ + nx_string_t nxstr; + size_t size = MultiByteToWideChar(CP_UTF8, 0, str, -1, 0,0); + if (!size) + { + return 0; + } + + nxstr = NXStringMalloc(size-1); + if (nxstr) + { + if (!MultiByteToWideChar(CP_UTF8, 0, str, -1, nxstr->string, (int)size)) + { + NXStringFree(string_heap, nxstr); + return 0; + } + } + + return nxstr; +} + +int NXStringCreateWithUTF8(nx_string_t *new_value, const char *str) +{ + size_t size; + nx_string_t nxstr; + + if (!str) + { + return NErr_Empty; + } + + size = MultiByteToWideChar(CP_UTF8, 0, str, -1, 0,0); + if (!size) + { + return NErr_Error; + } + + nxstr = NXStringMalloc(size-1); + if (!nxstr) + { + return NErr_OutOfMemory; + } + + if (!MultiByteToWideChar(CP_UTF8, 0, str, -1, nxstr->string, (int)size)) + { + NXStringFree(string_heap, nxstr); + return NErr_Error; + } + + *new_value = nxstr; + return NErr_Success; +} + +int NXStringCreateWithUTF16(nx_string_t *new_value, const wchar_t *str) +{ + size_t size; + nx_string_t nxstr; + + if (!str) + { + return NErr_Empty; + } + + size = wcslen(str); + nxstr = NXStringMalloc(size); + if (!nxstr) + { + return NErr_OutOfMemory; + } + + memcpy(nxstr->string, str, size*sizeof(wchar_t)); + nxstr->string[size]=0; + *new_value = nxstr; + return NErr_Success; +} + +int NXStringCreateWithCString(nx_string_t *new_value, const char *str, nx_charset_t charset) +{ + nx_string_t nxstr; + size_t size = MultiByteToWideChar(charset, 0, str, -1, 0,0); + if (!size) + { + return NErr_Error; + } + + nxstr = NXStringMalloc(size-1); + if (!nxstr) + { + return NErr_OutOfMemory; + } + + if (!MultiByteToWideChar(charset, 0, str, -1, nxstr->string, (int)size)) + { + NXStringFree(string_heap, nxstr); + return NErr_Error; + } + + *new_value = nxstr; + return NErr_Success; +} + +nx_string_t NXStringRetain(nx_string_t string) +{ + if (!string) + { + return 0; + } + + nx_atomic_inc(&string->ref_count); + return string; +} + +void NXStringRelease(nx_string_t string) +{ + if (string) + { + if (nx_atomic_dec(&string->ref_count) == 0) + { + NXStringFree(string_heap, string); + } + } +} + +nx_string_t NXStringCreateFromPath(const wchar_t *folder, const wchar_t *filename) +{ + nx_string_t pathstr = NXStringMalloc(MAX_PATH); + if (pathstr) + { + PathCombineW(pathstr->string, folder, filename); + pathstr->len = wcslen(pathstr->string); + } + return pathstr; +} + +nx_string_t NXStringCreateFromUInt64(uint64_t value) +{ + nx_string_t intstr = NXStringMalloc(21); + if (intstr) + { + _ui64tow(value, intstr->string, 10); + intstr->len = wcslen(intstr->string); + } + return intstr; +} + +int NXStringCreateWithUInt64(nx_string_t *new_value, uint64_t value) +{ + nx_string_t intstr = NXStringMalloc(21); + if (!intstr) + { + return NErr_OutOfMemory; + } + + _ui64tow(value, intstr->string, 10); + intstr->len = wcslen(intstr->string); + *new_value = intstr; + return NErr_Success; +} + +int NXStringCreateWithInt64(nx_string_t *new_value, int64_t value) +{ + nx_string_t intstr = NXStringMalloc(21); + if (!intstr) + { + return NErr_OutOfMemory; + } + + _i64tow(value, intstr->string, 10); + intstr->len = wcslen(intstr->string); + *new_value = intstr; + return NErr_Success; +} + +int NXStringCreateWithBytes(nx_string_t *new_string, const void *data, size_t len, nx_charset_t charset) +{ + nx_string_t nxstr; + if (!len) + { + return NXStringCreateEmpty(new_string); + } + if (charset == nx_charset_utf16le) + { + nxstr = NXStringMalloc(len/2); + if (nxstr) + { + memcpy(nxstr->string, data, len); + nxstr->string[len/2]=0; + nxstr->len = len/2; + *new_string = nxstr; + return NErr_Success; + } + else + { + return NErr_OutOfMemory; + } + } + else if (charset == nx_charset_utf16be) + { + nxstr = NXStringMalloc(len/2); + if (nxstr) + { + LCMapString(LOCALE_INVARIANT, LCMAP_BYTEREV, (LPCWSTR)data, (int)len/2, nxstr->string, (int)len/2); + nxstr->string[len/2]=0; + nxstr->len = len/2; + *new_string = nxstr; + return NErr_Success; + } + else + { + return NErr_OutOfMemory; + } + } + else + { + int size = MultiByteToWideChar((UINT)charset, 0, (const char *)data, (int)len, 0, 0); + if (!size) + { + return NErr_Error; + } + + nxstr = NXStringMalloc(size); + if (nxstr) + { + if (!MultiByteToWideChar((UINT)charset, 0, (const char *)data, (int)len, nxstr->string, size)) + { + NXStringFree(string_heap, nxstr); + return NErr_Error; + } + nxstr->string[size]=0; + nxstr->len = size; + *new_string = nxstr; + return NErr_Success; + } + else + { + return NErr_OutOfMemory; + } + } +} + +size_t NXStringGetLength(nx_string_t string) +{ + return (string ? string->len : 0); +} + +/* --- Keyword (ASCII) comparison --- */ +int NXStringKeywordCompareWithCString(nx_string_t string, const char *compare_to) +{ + const wchar_t *src = string->string; + const char *dst = compare_to; + + int ret = 0 ; + + while( ! (ret = (int)((*src & ~0x20) - (*dst & ~0x20))) && *dst) + { + ++src, ++dst; + } + + if ( ret < 0 ) + { + ret = -1 ; + } + else if ( ret > 0 ) + { + ret = 1 ; + } + return( ret ); +} + +int NXStringKeywordCompare(nx_string_t string, nx_string_t compare_to) +{ + const wchar_t *src = string->string; + const wchar_t *dst = compare_to->string; + + int ret = 0 ; + + while( ! (ret = (int)((*src & ~0x20) - (*dst & ~0x20))) && *dst) + { + ++src, ++dst; + } + + if ( ret < 0 ) + { + ret = -1 ; + } + else if ( ret > 0 ) + { + ret = 1 ; + } + return( ret ); +} + +int NXStringKeywordCaseCompare(nx_string_t string, nx_string_t compare_to) +{ + const wchar_t *src = string->string; + const wchar_t *dst = compare_to->string; + + int ret = 0 ; + + while( ! (ret = (int)(*src - (wchar_t)*dst)) && *dst) + { + ++src, ++dst; + } + + if ( ret < 0 ) + { + ret = -1 ; + } + else if ( ret > 0 ) + { + ret = 1 ; + } + + return( ret ); +} + +int NXStringCreateBasePathFromFilename(nx_string_t filename, nx_string_t *basepath) +{ + nx_string_t nxstr; + size_t len = filename->len; + while (len && filename->string[len-1] != '\\' && filename->string[len-1] != '/') + { + len--; + } + + if (!len) + { + return NErr_Empty; + } + + nxstr = NXStringMalloc(len); + if (!nxstr) + { + return NErr_OutOfMemory; + } + + memcpy(nxstr->string, filename->string, sizeof(wchar_t)*len); + nxstr->string[len]=0; + *basepath = nxstr; + return NErr_Success; +} + +int NXStringGetCString(nx_string_t string, char *user_buffer, size_t user_buffer_length, const char **out_cstring, size_t *out_cstring_length) +{ + size_t size; + + /* TODO: error check this with large strings and small user_buffer_length sizes */ + if (!string) + { + return NErr_NullPointer; + } + + if (user_buffer_length == 0) + return NErr_Insufficient; + + size = WideCharToMultiByte(CP_ACP, 0, string->string, (int)string->len, user_buffer, (int)user_buffer_length-1, NULL, NULL); + if (size == 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER) + size = user_buffer_length-1; + user_buffer[size]=0; + *out_cstring = user_buffer; + *out_cstring_length = (size_t)size; + return NErr_Success; +} + +int NXStringGetDoubleValue(nx_string_t string, double *value) +{ + if (!string) + return NErr_NullPointer; + + *value = wcstod(string->string, 0); + return NErr_Success; +} + +int NXStringGetBytesSize(size_t *byte_count, nx_string_t string, nx_charset_t charset, int flags) +{ + if (charset == nx_charset_utf16le) + { + if (flags & nx_string_get_bytes_size_null_terminate) + *byte_count = (string->len + 1)* sizeof(wchar_t); + else + *byte_count = string->len * sizeof(wchar_t); + return NErr_DirectPointer; + } + else + { + size_t size=0; + /*if (flags & nx_string_get_bytes_size_null_terminate) + size = WideCharToMultiByte(charset, 0, string->string, string->len, 0, 0, NULL, NULL); + else*/ + size = WideCharToMultiByte(charset, 0, string->string, (int)string->len, 0, 0, NULL, NULL); + + if (!size) + return NErr_Error; + + if (flags & nx_string_get_bytes_size_null_terminate) + *byte_count = size+1; + else + *byte_count = size; + + return NErr_Success; + } +} + +int NXStringGetBytesDirect(const void **bytes, size_t *length, nx_string_t string, nx_charset_t charset, int flags) +{ + if (charset == nx_charset_utf16le) + { + *bytes = string->string; + if (length) + { + if (flags & nx_string_get_bytes_size_null_terminate) + *length = (string->len+1) * sizeof(wchar_t); // TODO: overflow check + else + *length = string->len * sizeof(wchar_t); // TODO: overflow check + } + return NErr_Success; + } + else + { + return NErr_Error; + } + +} + +int NXStringGetBytes(size_t *bytes_copied, nx_string_t string, void *bytes, size_t length, nx_charset_t charset, int flags) +{ + if (charset == nx_charset_utf16le) + { + length/=2; + + if (flags & nx_string_get_bytes_size_null_terminate) + { + if (length == 0) + return NErr_Insufficient; + + length--; + } + + if (length > string->len) + length = string->len; + wmemcpy((wchar_t *)bytes, string->string, length); + + if (flags & nx_string_get_bytes_size_null_terminate) + ((wchar_t *)bytes)[length++]=0; + + if (bytes_copied) + *bytes_copied = length * 2; + return NErr_Success; + } + else + { + size_t size=0; + if (flags & nx_string_get_bytes_size_null_terminate) + { + size = WideCharToMultiByte(charset, 0, string->string, (int)string->len, (LPSTR)bytes, (int)length-1, NULL, NULL); + ((char *)bytes)[size]=0; + } + else + { + size = WideCharToMultiByte(charset, 0, string->string, (int)string->len, (LPSTR)bytes, (int)length, NULL, NULL); + } + + if (!size) + { + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) + { + if (flags & nx_string_get_bytes_size_null_terminate) + size = length-1; + else + size=length; + } + else + { + return NErr_Error; + } + } + + if (bytes_copied) + { + if (flags & nx_string_get_bytes_size_null_terminate) + { + if (size) + *bytes_copied = size+1; + else + *bytes_copied = length+1; + } + else + { + if (size) + *bytes_copied = size; + else + *bytes_copied = length; + } + } + return NErr_Success; + } +} + +int NXStringGetIntegerValue(nx_string_t string, int *value) +{ + *value = wcstol(string->string, 0, 10); + return NErr_Success; +} + +int NXStringGetGUIDValue(nx_string_t string, GUID *out_guid) +{ + /* TODO: it'd be nice if this was a bit more flexible on input, e.g. no dashes vs dashes */ + GUID guid = GUID_NULL; + size_t offset = 0; + int Data1, Data2, Data3; + int Data4[8] = {0}; + + for (;;) + { + if (string->string[offset] == '{') + { + offset++; + } + else if (string->string[offset] == ' ') + { + offset++; + } + else + { + break; + } + } + + //{ 0x1b3ca60c, 0xda98, 0x4826, { 0xb4, 0xa9, 0xd7, 0x97, 0x48, 0xa5, 0xfd, 0x73 } }; + swscanf( string->string, L"%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", + &Data1, &Data2, &Data3, Data4 + 0, Data4 + 1, + Data4 + 2, Data4 + 3, Data4 + 4, Data4 + 5, Data4 + 6, Data4 + 7 ); + + // Cross assign all the values + guid.Data1 = Data1; + guid.Data2 = Data2; + guid.Data3 = Data3; + guid.Data4[0] = Data4[0]; + guid.Data4[1] = Data4[1]; + guid.Data4[2] = Data4[2]; + guid.Data4[3] = Data4[3]; + guid.Data4[4] = Data4[4]; + guid.Data4[5] = Data4[5]; + guid.Data4[6] = Data4[6]; + guid.Data4[7] = Data4[7]; + + *out_guid = guid; + return NErr_Success; +} + +nx_compare_result NXStringCompare(nx_string_t string1, nx_string_t string2, nx_compare_options options) +{ + int compareFlags = 0; + + if (0 != (nx_compare_case_insensitive & options)) + { + compareFlags |= NORM_IGNORECASE; + } + return CompareString(LOCALE_USER_DEFAULT, compareFlags, string1->string, -1, string2->string, -1) - 2; +} + +int NXStringCreateWithFormatting(nx_string_t *new_string, const char *format, ...) +{ + size_t cch, ret; + char *temp = 0; + va_list v; + va_start(v, format); + + cch = _vscprintf(format, v); + if (cch == -1) + { + return NErr_Error; + } + + if (cch > 256) + { + temp = (char *)malloc(cch+1); + if (!temp) + { + return NErr_OutOfMemory; + } + vsprintf(temp, format, v); + + ret = NXStringCreateWithUTF8(new_string, temp); + free(temp); + } + else + { + temp = (char *)_malloca(cch+1); + if (!temp) + { + return NErr_OutOfMemory; + } + vsprintf(temp, format, v); + ret = NXStringCreateWithUTF8(new_string, temp); + } + va_end(v); + return (int)ret; +}
\ No newline at end of file diff --git a/Src/replicant/nx/win/nxstring.h b/Src/replicant/nx/win/nxstring.h new file mode 100644 index 00000000..5e07777a --- /dev/null +++ b/Src/replicant/nx/win/nxstring.h @@ -0,0 +1,95 @@ +#pragma once +#include "../../foundation/types.h" +#include <windows.h> +#include "../../nx/nxapi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + typedef enum + { + nx_charset_ascii = 20127, + nx_charset_latin1 = 28591, + nx_charset_system = CP_ACP, + nx_charset_utf8 = CP_UTF8, + nx_charset_utf16le = 1200, + nx_charset_utf16be = 1201, + } nx_charset_t; + + typedef struct nx_string_struct_t + { + size_t ref_count; + size_t len; + wchar_t string[1]; // utf-16 + } nx_string_struct_t, *nx_string_t; + + enum + { + nx_compare_less_than = -1, + nx_compare_equal_to = 0, + nx_compare_greater_than = 1, + }; + typedef int nx_compare_result; + + enum + { + nx_compare_default = 0, + nx_compare_case_insensitive = ( 1 << 0), + }; + typedef unsigned long nx_compare_options; + + NX_API int NXStringSetHeap(HANDLE string_heap); + NX_API nx_string_t NXStringCreateFromPath(const wchar_t *folder, const wchar_t *filename); + NX_API nx_string_t NXStringCreate(const wchar_t *str); + NX_API nx_string_t NXStringCreateWithHeap(HANDLE heap, const wchar_t *str); + NX_API nx_string_t NXStringMallocWithHeap(HANDLE heap, size_t characters); + NX_API nx_string_t NXStringMalloc(size_t characters); + NX_API nx_string_t NXStringRealloc(nx_string_t, size_t characters); + + NX_API nx_string_t NXStringRetain(nx_string_t string); + NX_API void NXStringRelease(nx_string_t string); + + NX_API nx_string_t NXStringCreateFromUTF8(const char *str); + NX_API int NXStringCreateWithUTF8(nx_string_t *new_value, const char *str); + NX_API int NXStringCreateWithUTF16(nx_string_t *new_value, const wchar_t *str); + NX_API int NXStringCreateWithCString(nx_string_t *new_value, const char *str, nx_charset_t charset); + NX_API nx_string_t NXStringCreateFromUInt64(uint64_t value); + NX_API int NXStringCreateWithUInt64(nx_string_t *new_value, uint64_t value); + NX_API int NXStringCreateWithInt64(nx_string_t *new_value, int64_t value); + NX_API int NXStringCreateWithBytes(nx_string_t *new_string, const void *data, size_t len, nx_charset_t charset); + NX_API int NXStringCreateEmpty(nx_string_t *new_string); + NX_API int NXStringCreateWithFormatting(nx_string_t *new_string, const char *format, ...); + + NX_API size_t NXStringGetLength(nx_string_t string); + + /* returns strcmp style return. compare_to is treated as an ASCII string. + if compare_to has non-ASCII characters, results are undetermined */ + NX_API int NXStringKeywordCompareWithCString(nx_string_t string, const char *compare_to); + NX_API int NXStringKeywordCompare(nx_string_t string, nx_string_t compare_to); + + NX_API int NXStringKeywordCaseCompare(nx_string_t string, nx_string_t compare_to); + + /* creates an NXString with the base path from the passed in filename (retains an appended \) */ + NX_API int NXStringCreateBasePathFromFilename(nx_string_t filename, nx_string_t *basepath); + + NX_API int NXStringGetCString(nx_string_t string, char *user_buffer, size_t user_buffer_length, const char **out_cstring, size_t *out_cstring_length); + NX_API int NXStringGetDoubleValue(nx_string_t string, double *value); + NX_API int NXStringGetIntegerValue(nx_string_t string, int *value); + NX_API int NXStringGetGUIDValue(nx_string_t string, GUID *guid); + + static const int nx_string_get_bytes_size_null_terminate = 1; // pass this to null terminate the string + /* returns byte count with enough room to store a converted string + note: if this returns NErr_DirectPointer, you can call NXStringGetBytesDirect to directly retrieve a pointer. */ + NX_API int NXStringGetBytesSize(size_t *byte_count, nx_string_t string, nx_charset_t charset, int flags); + /* if possible, retrieves a pointer to bytes. + the length returned depends on whether or not you passed nx_string_get_bytes_size_null_terminate + note: the pointer you get will be invalid after you call NXStringRelease on the string passed in */ + NX_API int NXStringGetBytesDirect(const void **bytes, size_t *length, nx_string_t string, nx_charset_t charset, int flags); + NX_API int NXStringGetBytes(size_t *bytes_copied, nx_string_t string, void *bytes, size_t length, nx_charset_t charset, int flags); + + NX_API nx_compare_result NXStringCompare(nx_string_t string1, nx_string_t string2, nx_compare_options options); + +#ifdef __cplusplus +} +#endif
\ No newline at end of file diff --git a/Src/replicant/nx/win/nxthread.c b/Src/replicant/nx/win/nxthread.c new file mode 100644 index 00000000..0c049ad4 --- /dev/null +++ b/Src/replicant/nx/win/nxthread.c @@ -0,0 +1,25 @@ +#include "nxthread.h" +#include "foundation/error.h" + +int NXThreadCreate(nx_thread_t *thread, nx_thread_func_t thread_function, nx_thread_parameter_t parameter) +{ + *thread = (nx_thread_t)CreateThread(0, 0, thread_function, parameter, 0, 0); + return NErr_Success; +} + +int NXThreadJoin(nx_thread_t t, nx_thread_return_t *retval) +{ + if (!t) + return NErr_NullPointer; + WaitForSingleObject((HANDLE)t, INFINITE); + if (retval) + GetExitCodeThread((HANDLE)t, retval); + CloseHandle((HANDLE)t); + return NErr_Success; +} + +int NXThreadCurrentSetPriority(int priority) +{ + SetThreadPriority(GetCurrentThread(), priority); + return NErr_Success; +}
\ No newline at end of file diff --git a/Src/replicant/nx/win/nxthread.h b/Src/replicant/nx/win/nxthread.h new file mode 100644 index 00000000..5b2c2561 --- /dev/null +++ b/Src/replicant/nx/win/nxthread.h @@ -0,0 +1,32 @@ + +#pragma once +#include "nx/nxapi.h" +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include <windows.h> + +#ifdef __cplusplus +extern "C" { +#endif + + typedef struct nx_thread_struct_t { size_t dummy; } *nx_thread_t; + typedef DWORD nx_thread_return_t; + typedef void *nx_thread_parameter_t; +#define NXTHREADCALL CALLBACK + typedef nx_thread_return_t (NXTHREADCALL *nx_thread_func_t)(nx_thread_parameter_t parameter); + + // TODO: add parameters for things like stack size +NX_API int NXThreadCreate(nx_thread_t *thread, nx_thread_func_t thread_function, nx_thread_parameter_t parameter); +NX_API int NXThreadJoin(nx_thread_t t, nx_thread_return_t *retval); + +enum +{ + NX_THREAD_PRIORITY_PLAYBACK=THREAD_PRIORITY_HIGHEST, +}; +// sets priority of current thread +NX_API int NXThreadCurrentSetPriority(int priority); + +#ifdef __cplusplus +} +#endif
\ No newline at end of file diff --git a/Src/replicant/nx/win/nxtime.h b/Src/replicant/nx/win/nxtime.h new file mode 100644 index 00000000..dad71c6b --- /dev/null +++ b/Src/replicant/nx/win/nxtime.h @@ -0,0 +1,10 @@ +#pragma once +#include "../../foundation/types.h" +#include "../../nx/nxapi.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef uint64_t nx_time_unix_64_t; +#ifdef __cplusplus +} +#endif
\ No newline at end of file diff --git a/Src/replicant/nx/win/nxuri.c b/Src/replicant/nx/win/nxuri.c new file mode 100644 index 00000000..afe99a21 --- /dev/null +++ b/Src/replicant/nx/win/nxuri.c @@ -0,0 +1,258 @@ +#include "nxuri.h" +#include <stdlib.h> +#include "foundation/atomics.h" +#include "foundation/error.h" +#include "nxstring.h" // for string_heap +#include "foundation/atomics.h" + +HANDLE string_heap; + +int NXStringFree(HANDLE heap, nx_string_t str); + +nx_uri_t NXURIRetain(nx_uri_t string) +{ + if (!string) + { + return 0; + } + + nx_atomic_inc(&string->ref_count); + return string; +} + +void NXURIRelease(nx_uri_t string) +{ + if (string) + { + if (nx_atomic_dec(&string->ref_count) == 0) + { + NXStringFree(string_heap, (nx_string_t)string); + } + } +} + +// don't include null terminator here +nx_uri_t NXURIMalloc(size_t characters) +{ + return (nx_uri_t)NXStringMalloc(characters); +} + +int NXURICreateWithNXString(nx_uri_t *uri, nx_string_t string) +{ + if (!string) + { + return NErr_Empty; + } + + *uri = NXURIRetain((nx_uri_t)string); + return NErr_Success; +} + +int NXURICreateFromPath(nx_uri_t *uri, const wchar_t *filename, const nx_uri_t path) +{ + size_t filename_length = wcslen(filename); + size_t path_length = path->len; + size_t total_length = filename_length + path_length; /* TODO: check for overflow */ + int need_slash = 1; + nx_uri_t output=0; + if (path_length && (path->string[path_length-1] == '/' || path->string[path_length-1] == '\\')) + { + need_slash=0; + } + else + { + total_length++; /* TODO: check for overflow */ + } + + output = NXURIMalloc(total_length); + if (!output) + { + return NErr_OutOfMemory; + } + + wmemcpy(output->string, path->string, path_length); + if (need_slash) + { + output->string[path_length]='\\'; /* TODO: URL detection to know whether to add / or \\ */ + wcscpy(&output->string[path_length+1], filename); + } + else + { + wcscpy(&output->string[path_length], filename); + } + + *uri = output; + return NErr_Success; +} + +int NXURICreateWithPath(nx_uri_t *uri, const nx_uri_t filename, const nx_uri_t path) +{ + size_t filename_length = filename->len; + size_t path_length = path->len; + size_t total_length = filename_length + path_length; /* TODO: check for overflow */ + int need_slash = 1; + nx_uri_t output=0; + if (path_length && (path->string[path_length-1] == '/' || path->string[path_length-1] == '\\')) + { + need_slash=0; + } + else + { + total_length++; /* TODO: check for overflow */ + } + + output = NXURIMalloc(total_length); + if (!output) + { + return NErr_OutOfMemory; + } + + wmemcpy(output->string, path->string, path_length); + if (need_slash) + { + output->string[path_length]='\\'; /* TODO: URL detection to know whether to add / or \\ */ + wcscpy(&output->string[path_length+1], filename->string); + } + else + { + wcscpy(&output->string[path_length], filename->string); + } + + *uri = output; + return NErr_Success; +} + +int NXURIGetNXString(nx_string_t *string, nx_uri_t uri) +{ + *string = (nx_string_t)NXURIRetain(uri); + return NErr_Success; +} + +static const wchar_t *FindFilename(nx_uri_t filename) +{ + size_t position; + if (!filename || !filename->string || !filename->len) + { + return 0; + } + + position=filename->len; + while (position--) + { + wchar_t c = filename->string[position]; + if (c == '/' || c == '\\') + { + return &filename->string[position+1]; + } + } + return 0; +} + +int NXURICreateTempForFilepath(nx_uri_t *out_temp, nx_uri_t filename) +{ + nx_uri_t new_uri; + size_t path_length = 0; + wchar_t temp_part[64] = {0}; +#if _WIN32_WINNT >= 0x600 + int temp_length = wsprintf(temp_part, L".%x-%I64x-%d.tmp", GetCurrentThreadId(), GetTickCount64(), rand()); +#else + int temp_length = wsprintf(temp_part, L".%x-%Ix-%d.tmp", GetCurrentThreadId(), GetTickCount(), rand()); +#endif + const wchar_t *filepart = FindFilename(filename); + if (filepart) + { + path_length = (filepart - filename->string); + } + else + { + path_length=0; + } + new_uri = NXURIMalloc(path_length+temp_length); + if (!new_uri) + { + return NErr_OutOfMemory; + } + wmemcpy(new_uri->string, filename->string, path_length); + wmemcpy(new_uri->string+path_length, temp_part, temp_length); + new_uri->string[path_length+temp_length]=0; + *out_temp = new_uri; + return NErr_Success; +} + +int NXURICreateWithUTF8(nx_uri_t *value, const char *utf8) +{ + nx_string_t nx_filename; + nx_uri_t uri_filename; + + int ret = NXStringCreateWithUTF8(&nx_filename, utf8); + if (ret != NErr_Success) + { + return ret; + } + + ret = NXURICreateWithNXString(&uri_filename, nx_filename); + NXStringRelease(nx_filename); + if (ret != NErr_Success) + return ret; + + *value = uri_filename; + return NErr_Success; +} + +int NXURICreateRemovingFilename(nx_uri_t *out_uri, nx_uri_t filename) +{ + nx_uri_t new_uri; + size_t path_length; + + const wchar_t *filepart = FindFilename(filename); + if (filepart) + { + path_length = (filepart - filename->string); + } + else + { + path_length=0; + } + new_uri = NXURIMalloc(path_length); + if (!new_uri) + { + return NErr_OutOfMemory; + } + wmemcpy(new_uri->string, filename->string, path_length); + new_uri->string[path_length]=0; + *out_uri = new_uri; + return NErr_Success; +} + +int NXURICreateTemp(nx_uri_t *out_temp) +{ + return NXURICreateTempWithExtension(out_temp, "tmp"); +} + +int NXURICreateTempWithExtension(nx_uri_t *out_temp, const char *extension) +{ + nx_uri_t new_uri; + wchar_t temppath[MAX_PATH-14] = {0}; // MAX_PATH-14 'cause MSDN said so + int path_length = GetTempPathW(MAX_PATH-14, temppath); + wchar_t temp_part[64] = {0}; +#if _WIN32_WINNT >= 0x600 + int temp_length = wsprintf(temp_part, L".%x-%I64x-%d.%S", GetCurrentThreadId(), GetTickCount64(), rand(), extension); +#else + int temp_length = wsprintf(temp_part, L".%x-%Ix-%d.%S", GetCurrentThreadId(), GetTickCount(), rand(), extension); +#endif + new_uri = NXURIMalloc(path_length+temp_length); + if (!new_uri) + { + return NErr_OutOfMemory; + } + wmemcpy(new_uri->string, temppath, path_length); + wmemcpy(new_uri->string+path_length, temp_part, temp_length); + new_uri->string[path_length+temp_length]=0; + *out_temp = new_uri; + return NErr_Success; +} + +size_t NXURIGetLength(nx_uri_t string) +{ + return (string ? string->len : 0); +}
\ No newline at end of file diff --git a/Src/replicant/nx/win/nxuri.h b/Src/replicant/nx/win/nxuri.h new file mode 100644 index 00000000..c4a7bd1a --- /dev/null +++ b/Src/replicant/nx/win/nxuri.h @@ -0,0 +1,44 @@ +#pragma once +#include "../../foundation/types.h" +#include "../../nx/nxapi.h" +#include "../../nx/nxstring.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + /* this thing is meant to be identical to nx_string_t, but we want to try to protect it so they don't get easily cast to nx_string_t + since they aren't the same on all platforms */ + typedef struct nx_uri_struct_t + { + size_t ref_count; + size_t len; + wchar_t string[1]; // utf-16 + } nx_uri_struct_t, *nx_uri_t; + + NX_API nx_uri_t NXURIRetain(nx_uri_t string); + NX_API void NXURIRelease(nx_uri_t string); + + NX_API nx_uri_t NXURIMalloc(size_t characters); + NX_API int NXURICreateWithNXString(nx_uri_t *uri, nx_string_t string); + NX_API int NXURICreateFromPath(nx_uri_t *uri, const wchar_t *filename, const nx_uri_t path); // windows only + NX_API int NXURICreateWithPath(nx_uri_t *uri, const nx_uri_t filename, const nx_uri_t path); + NX_API int NXURICreateWithNXString(nx_uri_t *new_value, nx_string_t string); + NX_API int NXURICreateTempForFilepath(nx_uri_t *out_temp, nx_uri_t filename); + NX_API int NXURICreateTempWithExtension(nx_uri_t *out_temp, const char *extension); + NX_API int NXURICreateWithUTF8(nx_uri_t *value, const char *utf8); + NX_API int NXURICreateTemp(nx_uri_t *out_temp); + + // replaces only the filename portion of the path with the desired filename + // e.g., filepath = /path/to/1.mp3, *out_uri = /path/to/ + NX_API int NXURICreateRemovingFilename(nx_uri_t *out_uri, nx_uri_t filename); + + + NX_API int NXURIGetNXString(nx_string_t *string, nx_uri_t uri); + + NX_API size_t NXURIGetLength(nx_uri_t string); + +#ifdef __cplusplus +} +#endif
\ No newline at end of file |