aboutsummaryrefslogtreecommitdiff
path: root/lib/libhts
diff options
context:
space:
mode:
authortheuni <theuni-nospam-@xbmc.org>2011-01-24 16:05:21 -0500
committertheuni <theuni-nospam-@xbmc.org>2011-01-24 16:05:21 -0500
commitc51b1189e3d5353e842991f5859ddcea0f73e426 (patch)
treeef2cb8a6184699aa614f3655dca4ce661cdc108e /lib/libhts
parentbe61ebdc9e897fe40c6f371111724de79ddee8d5 (diff)
Merged cptspiff's code-reshuffle branch.
Squashed commit due to build breakage during code-reshuffle history. Conflicts: xbmc/Util.cpp xbmc/cdrip/CDDARipper.cpp xbmc/filesystem/Directory.cpp xbmc/filesystem/File.cpp
Diffstat (limited to 'lib/libhts')
-rw-r--r--lib/libhts/Makefile14
-rw-r--r--lib/libhts/Win32/include/getopt.h84
-rw-r--r--lib/libhts/Win32/include/inttypes.h306
-rw-r--r--lib/libhts/Win32/include/msvc.h34
-rw-r--r--lib/libhts/Win32/include/stdint.h222
-rw-r--r--lib/libhts/Win32/include/sys/queue.h574
-rw-r--r--lib/libhts/Win32/include/unistd.h47
-rw-r--r--lib/libhts/Win32/libhts_2003.sln21
-rw-r--r--lib/libhts/Win32/libhts_2003.vcproj161
-rw-r--r--lib/libhts/Win32/libhts_2008.sln20
-rw-r--r--lib/libhts/Win32/libhts_2008.vcproj237
-rw-r--r--lib/libhts/Win32/libhts_2010.vcxproj109
-rw-r--r--lib/libhts/Win32/libhts_2010.vcxproj.filters64
-rw-r--r--lib/libhts/hts_strtab.h61
-rw-r--r--lib/libhts/htsatomic.c19
-rw-r--r--lib/libhts/htsatomic.h37
-rw-r--r--lib/libhts/htsbuf.c255
-rw-r--r--lib/libhts/htsbuf.h65
-rw-r--r--lib/libhts/htsmsg.c578
-rw-r--r--lib/libhts/htsmsg.h263
-rw-r--r--lib/libhts/htsmsg_binary.c283
-rw-r--r--lib/libhts/htsmsg_binary.h34
-rw-r--r--lib/libhts/htsq.h146
-rw-r--r--lib/libhts/htsstr.c193
-rw-r--r--lib/libhts/htsstr.h33
-rw-r--r--lib/libhts/net.h51
-rw-r--r--lib/libhts/net_posix.c342
-rw-r--r--lib/libhts/net_winsock.c381
-rw-r--r--lib/libhts/sha1.c225
-rw-r--r--lib/libhts/sha1.h36
30 files changed, 4895 insertions, 0 deletions
diff --git a/lib/libhts/Makefile b/lib/libhts/Makefile
new file mode 100644
index 0000000000..078d4f1b1b
--- /dev/null
+++ b/lib/libhts/Makefile
@@ -0,0 +1,14 @@
+INCLUDES=-I.
+
+SRCS = htsmsg.c \
+ htsmsg_binary.c \
+ htsbuf.c \
+ htsstr.c \
+ net_posix.c \
+ sha1.c \
+
+CFLAGS=-std=c99 -D_GNU_SOURCE
+LIB=libhts.a
+
+include ../../Makefile.include
+-include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(SRCS)))
diff --git a/lib/libhts/Win32/include/getopt.h b/lib/libhts/Win32/include/getopt.h
new file mode 100644
index 0000000000..6b6f643b7d
--- /dev/null
+++ b/lib/libhts/Win32/include/getopt.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 1987, 1993, 1994, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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 __GETOPT_H__
+#define __GETOPT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int opterr; /* if error message should be printed */
+extern int optind; /* index into parent argv vector */
+extern int optopt; /* character checked for validity */
+extern int optreset; /* reset getopt */
+extern char *optarg; /* argument associated with option */
+
+int getopt (int, char * const *, const char *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GETOPT_H__ */
+
+#ifndef __UNISTD_GETOPT__
+#ifndef __GETOPT_LONG_H__
+#define __GETOPT_LONG_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct option {
+ const char *name;
+ int has_arg;
+ int *flag;
+ int val;
+};
+
+int getopt_long (int, char *const *, const char *, const struct option *, int *);
+#ifndef HAVE_DECL_GETOPT
+#define HAVE_DECL_GETOPT 1
+#endif
+
+#define no_argument 0
+#define required_argument 1
+#define optional_argument 2
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GETOPT_LONG_H__ */
+#endif /* __UNISTD_GETOPT__ */
diff --git a/lib/libhts/Win32/include/inttypes.h b/lib/libhts/Win32/include/inttypes.h
new file mode 100644
index 0000000000..1475fbf02f
--- /dev/null
+++ b/lib/libhts/Win32/include/inttypes.h
@@ -0,0 +1,306 @@
+// ISO C9x compliant inttypes.h for Microsoft Visual Studio
+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
+//
+// Copyright (c) 2006 Alexander Chemeris
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// 2. 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.
+//
+// 3. The name of the author may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 _MSC_VER // [
+#error "Use this header only with Microsoft Visual C++ compilers!"
+#endif // _MSC_VER ]
+
+#ifndef _MSC_INTTYPES_H_ // [
+#define _MSC_INTTYPES_H_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#include <stdint.h>
+
+// 7.8 Format conversion of integer types
+
+typedef struct {
+ intmax_t quot;
+ intmax_t rem;
+} imaxdiv_t;
+
+// 7.8.1 Macros for format specifiers
+
+#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198
+
+// The fprintf macros for signed integers are:
+#define PRId8 "d"
+#define PRIi8 "i"
+#define PRIdLEAST8 "d"
+#define PRIiLEAST8 "i"
+#define PRIdFAST8 "d"
+#define PRIiFAST8 "i"
+
+#define PRId16 "hd"
+#define PRIi16 "hi"
+#define PRIdLEAST16 "hd"
+#define PRIiLEAST16 "hi"
+#define PRIdFAST16 "hd"
+#define PRIiFAST16 "hi"
+
+#define PRId32 "I32d"
+#define PRIi32 "I32i"
+#define PRIdLEAST32 "I32d"
+#define PRIiLEAST32 "I32i"
+#define PRIdFAST32 "I32d"
+#define PRIiFAST32 "I32i"
+
+#define PRId64 "I64d"
+#define PRIi64 "I64i"
+#define PRIdLEAST64 "I64d"
+#define PRIiLEAST64 "I64i"
+#define PRIdFAST64 "I64d"
+#define PRIiFAST64 "I64i"
+
+#define PRIdMAX "I64d"
+#define PRIiMAX "I64i"
+
+#define PRIdPTR "Id"
+#define PRIiPTR "Ii"
+
+// The fprintf macros for unsigned integers are:
+#define PRIo8 "o"
+#define PRIu8 "u"
+#define PRIx8 "x"
+#define PRIX8 "X"
+#define PRIoLEAST8 "o"
+#define PRIuLEAST8 "u"
+#define PRIxLEAST8 "x"
+#define PRIXLEAST8 "X"
+#define PRIoFAST8 "o"
+#define PRIuFAST8 "u"
+#define PRIxFAST8 "x"
+#define PRIXFAST8 "X"
+
+#define PRIo16 "ho"
+#define PRIu16 "hu"
+#define PRIx16 "hx"
+#define PRIX16 "hX"
+#define PRIoLEAST16 "ho"
+#define PRIuLEAST16 "hu"
+#define PRIxLEAST16 "hx"
+#define PRIXLEAST16 "hX"
+#define PRIoFAST16 "ho"
+#define PRIuFAST16 "hu"
+#define PRIxFAST16 "hx"
+#define PRIXFAST16 "hX"
+
+#define PRIo32 "I32o"
+#define PRIu32 "I32u"
+#define PRIx32 "I32x"
+#define PRIX32 "I32X"
+#define PRIoLEAST32 "I32o"
+#define PRIuLEAST32 "I32u"
+#define PRIxLEAST32 "I32x"
+#define PRIXLEAST32 "I32X"
+#define PRIoFAST32 "I32o"
+#define PRIuFAST32 "I32u"
+#define PRIxFAST32 "I32x"
+#define PRIXFAST32 "I32X"
+
+#define PRIo64 "I64o"
+#define PRIu64 "I64u"
+#define PRIx64 "I64x"
+#define PRIX64 "I64X"
+#define PRIoLEAST64 "I64o"
+#define PRIuLEAST64 "I64u"
+#define PRIxLEAST64 "I64x"
+#define PRIXLEAST64 "I64X"
+#define PRIoFAST64 "I64o"
+#define PRIuFAST64 "I64u"
+#define PRIxFAST64 "I64x"
+#define PRIXFAST64 "I64X"
+
+#define PRIoMAX "I64o"
+#define PRIuMAX "I64u"
+#define PRIxMAX "I64x"
+#define PRIXMAX "I64X"
+
+#define PRIoPTR "Io"
+#define PRIuPTR "Iu"
+#define PRIxPTR "Ix"
+#define PRIXPTR "IX"
+
+// The fscanf macros for signed integers are:
+#define SCNd8 "d"
+#define SCNi8 "i"
+#define SCNdLEAST8 "d"
+#define SCNiLEAST8 "i"
+#define SCNdFAST8 "d"
+#define SCNiFAST8 "i"
+
+#define SCNd16 "hd"
+#define SCNi16 "hi"
+#define SCNdLEAST16 "hd"
+#define SCNiLEAST16 "hi"
+#define SCNdFAST16 "hd"
+#define SCNiFAST16 "hi"
+
+#define SCNd32 "ld"
+#define SCNi32 "li"
+#define SCNdLEAST32 "ld"
+#define SCNiLEAST32 "li"
+#define SCNdFAST32 "ld"
+#define SCNiFAST32 "li"
+
+#define SCNd64 "I64d"
+#define SCNi64 "I64i"
+#define SCNdLEAST64 "I64d"
+#define SCNiLEAST64 "I64i"
+#define SCNdFAST64 "I64d"
+#define SCNiFAST64 "I64i"
+
+#define SCNdMAX "I64d"
+#define SCNiMAX "I64i"
+
+#ifdef _WIN64 // [
+# define SCNdPTR "I64d"
+# define SCNiPTR "I64i"
+#else // _WIN64 ][
+# define SCNdPTR "ld"
+# define SCNiPTR "li"
+#endif // _WIN64 ]
+
+// The fscanf macros for unsigned integers are:
+#define SCNo8 "o"
+#define SCNu8 "u"
+#define SCNx8 "x"
+#define SCNX8 "X"
+#define SCNoLEAST8 "o"
+#define SCNuLEAST8 "u"
+#define SCNxLEAST8 "x"
+#define SCNXLEAST8 "X"
+#define SCNoFAST8 "o"
+#define SCNuFAST8 "u"
+#define SCNxFAST8 "x"
+#define SCNXFAST8 "X"
+
+#define SCNo16 "ho"
+#define SCNu16 "hu"
+#define SCNx16 "hx"
+#define SCNX16 "hX"
+#define SCNoLEAST16 "ho"
+#define SCNuLEAST16 "hu"
+#define SCNxLEAST16 "hx"
+#define SCNXLEAST16 "hX"
+#define SCNoFAST16 "ho"
+#define SCNuFAST16 "hu"
+#define SCNxFAST16 "hx"
+#define SCNXFAST16 "hX"
+
+#define SCNo32 "lo"
+#define SCNu32 "lu"
+#define SCNx32 "lx"
+#define SCNX32 "lX"
+#define SCNoLEAST32 "lo"
+#define SCNuLEAST32 "lu"
+#define SCNxLEAST32 "lx"
+#define SCNXLEAST32 "lX"
+#define SCNoFAST32 "lo"
+#define SCNuFAST32 "lu"
+#define SCNxFAST32 "lx"
+#define SCNXFAST32 "lX"
+
+#define SCNo64 "I64o"
+#define SCNu64 "I64u"
+#define SCNx64 "I64x"
+#define SCNX64 "I64X"
+#define SCNoLEAST64 "I64o"
+#define SCNuLEAST64 "I64u"
+#define SCNxLEAST64 "I64x"
+#define SCNXLEAST64 "I64X"
+#define SCNoFAST64 "I64o"
+#define SCNuFAST64 "I64u"
+#define SCNxFAST64 "I64x"
+#define SCNXFAST64 "I64X"
+
+#define SCNoMAX "I64o"
+#define SCNuMAX "I64u"
+#define SCNxMAX "I64x"
+#define SCNXMAX "I64X"
+
+#ifdef _WIN64 // [
+# define SCNoPTR "I64o"
+# define SCNuPTR "I64u"
+# define SCNxPTR "I64x"
+# define SCNXPTR "I64X"
+#else // _WIN64 ][
+# define SCNoPTR "lo"
+# define SCNuPTR "lu"
+# define SCNxPTR "lx"
+# define SCNXPTR "lX"
+#endif // _WIN64 ]
+
+#endif // __STDC_FORMAT_MACROS ]
+
+// 7.8.2 Functions for greatest-width integer types
+
+// 7.8.2.1 The imaxabs function
+#define imaxabs _abs64
+
+// 7.8.2.2 The imaxdiv function
+
+// This is modified version of div() function from Microsoft's div.c found
+// in %MSVC.NET%\crt\src\div.c
+#ifdef STATIC_IMAXDIV // [
+static
+#else // STATIC_IMAXDIV ][
+_inline
+#endif // STATIC_IMAXDIV ]
+imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)
+{
+ imaxdiv_t result;
+
+ result.quot = numer / denom;
+ result.rem = numer % denom;
+
+ if (numer < 0 && result.rem > 0) {
+ // did division wrong; must fix up
+ ++result.quot;
+ result.rem -= denom;
+ }
+
+ return result;
+}
+
+// 7.8.2.3 The strtoimax and strtoumax functions
+#define strtoimax _strtoi64
+#define strtoumax _strtoui64
+
+// 7.8.2.4 The wcstoimax and wcstoumax functions
+#define wcstoimax _wcstoi64
+#define wcstoumax _wcstoui64
+
+#define ssize_t int
+
+#endif // _MSC_INTTYPES_H_ ]
diff --git a/lib/libhts/Win32/include/msvc.h b/lib/libhts/Win32/include/msvc.h
new file mode 100644
index 0000000000..0a7ed2d3c8
--- /dev/null
+++ b/lib/libhts/Win32/include/msvc.h
@@ -0,0 +1,34 @@
+#ifdef WIN32
+
+#define strtoll(p, e, b) _strtoi64(p, e, b)
+#define snprintf _snprintf
+#define strcasecmp stricmp
+#define strncasecmp strnicmp
+#define strdup _strdup
+#if _MSC_VER < 1500
+#define vsnprintf _vsnprintf
+#endif
+
+static char * strndup(const char* str, size_t len)
+{
+ size_t i = 0;
+ char* p = (char*)str;
+ while(*p != 0 && i < len)
+ {
+ p++;
+ i++;
+ }
+ p = malloc(len+1);
+ memcpy(p, str, len);
+ p[len] = 0;
+ return p;
+}
+
+#ifndef M_PI
+#define M_PI 3.1415926535897932384626433832795
+#endif
+
+#define S_IFREG 0100000
+#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+
+#endif
diff --git a/lib/libhts/Win32/include/stdint.h b/lib/libhts/Win32/include/stdint.h
new file mode 100644
index 0000000000..81ecedc191
--- /dev/null
+++ b/lib/libhts/Win32/include/stdint.h
@@ -0,0 +1,222 @@
+// ISO C9x compliant stdint.h for Microsoft Visual Studio
+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
+//
+// Copyright (c) 2006 Alexander Chemeris
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// 2. 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.
+//
+// 3. The name of the author may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 _MSC_VER // [
+#error "Use this header only with Microsoft Visual C++ compilers!"
+#endif // _MSC_VER ]
+
+#ifndef _MSC_STDINT_H_ // [
+#define _MSC_STDINT_H_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#include <limits.h>
+
+// For Visual Studio 6 in C++ mode wrap <wchar.h> include with 'extern "C++" {}'
+// or compiler give many errors like this:
+// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
+#if (_MSC_VER < 1300) && defined(__cplusplus)
+ extern "C++" {
+#endif
+# include <wchar.h>
+#if (_MSC_VER < 1300) && defined(__cplusplus)
+ }
+#endif
+
+// 7.18.1 Integer types
+
+// 7.18.1.1 Exact-width integer types
+typedef __int8 int8_t;
+typedef __int16 int16_t;
+typedef __int32 int32_t;
+typedef __int64 int64_t;
+typedef unsigned __int8 uint8_t;
+typedef unsigned __int16 uint16_t;
+typedef unsigned __int32 uint32_t;
+typedef unsigned __int64 uint64_t;
+
+// 7.18.1.2 Minimum-width integer types
+typedef int8_t int_least8_t;
+typedef int16_t int_least16_t;
+typedef int32_t int_least32_t;
+typedef int64_t int_least64_t;
+typedef uint8_t uint_least8_t;
+typedef uint16_t uint_least16_t;
+typedef uint32_t uint_least32_t;
+typedef uint64_t uint_least64_t;
+
+// 7.18.1.3 Fastest minimum-width integer types
+typedef int8_t int_fast8_t;
+typedef int16_t int_fast16_t;
+typedef int32_t int_fast32_t;
+typedef int64_t int_fast64_t;
+typedef uint8_t uint_fast8_t;
+typedef uint16_t uint_fast16_t;
+typedef uint32_t uint_fast32_t;
+typedef uint64_t uint_fast64_t;
+
+// 7.18.1.4 Integer types capable of holding object pointers
+#ifdef _WIN64 // [
+ typedef __int64 intptr_t;
+ typedef unsigned __int64 uintptr_t;
+#else // _WIN64 ][
+ typedef int intptr_t;
+ typedef unsigned int uintptr_t;
+#endif // _WIN64 ]
+
+// 7.18.1.5 Greatest-width integer types
+typedef int64_t intmax_t;
+typedef uint64_t uintmax_t;
+
+
+// 7.18.2 Limits of specified-width integer types
+
+#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
+
+// 7.18.2.1 Limits of exact-width integer types
+#define INT8_MIN ((int8_t)_I8_MIN)
+#define INT8_MAX _I8_MAX
+#define INT16_MIN ((int16_t)_I16_MIN)
+#define INT16_MAX _I16_MAX
+#define INT32_MIN ((int32_t)_I32_MIN)
+#define INT32_MAX _I32_MAX
+#define INT64_MIN ((int64_t)_I64_MIN)
+#define INT64_MAX _I64_MAX
+#define UINT8_MAX _UI8_MAX
+#define UINT16_MAX _UI16_MAX
+#define UINT32_MAX _UI32_MAX
+#define UINT64_MAX _UI64_MAX
+
+// 7.18.2.2 Limits of minimum-width integer types
+#define INT_LEAST8_MIN INT8_MIN
+#define INT_LEAST8_MAX INT8_MAX
+#define INT_LEAST16_MIN INT16_MIN
+#define INT_LEAST16_MAX INT16_MAX
+#define INT_LEAST32_MIN INT32_MIN
+#define INT_LEAST32_MAX INT32_MAX
+#define INT_LEAST64_MIN INT64_MIN
+#define INT_LEAST64_MAX INT64_MAX
+#define UINT_LEAST8_MAX UINT8_MAX
+#define UINT_LEAST16_MAX UINT16_MAX
+#define UINT_LEAST32_MAX UINT32_MAX
+#define UINT_LEAST64_MAX UINT64_MAX
+
+// 7.18.2.3 Limits of fastest minimum-width integer types
+#define INT_FAST8_MIN INT8_MIN
+#define INT_FAST8_MAX INT8_MAX
+#define INT_FAST16_MIN INT16_MIN
+#define INT_FAST16_MAX INT16_MAX
+#define INT_FAST32_MIN INT32_MIN
+#define INT_FAST32_MAX INT32_MAX
+#define INT_FAST64_MIN INT64_MIN
+#define INT_FAST64_MAX INT64_MAX
+#define UINT_FAST8_MAX UINT8_MAX
+#define UINT_FAST16_MAX UINT16_MAX
+#define UINT_FAST32_MAX UINT32_MAX
+#define UINT_FAST64_MAX UINT64_MAX
+
+// 7.18.2.4 Limits of integer types capable of holding object pointers
+#ifdef _WIN64 // [
+# define INTPTR_MIN INT64_MIN
+# define INTPTR_MAX INT64_MAX
+# define UINTPTR_MAX UINT64_MAX
+#else // _WIN64 ][
+# define INTPTR_MIN INT32_MIN
+# define INTPTR_MAX INT32_MAX
+# define UINTPTR_MAX UINT32_MAX
+#endif // _WIN64 ]
+
+// 7.18.2.5 Limits of greatest-width integer types
+#define INTMAX_MIN INT64_MIN
+#define INTMAX_MAX INT64_MAX
+#define UINTMAX_MAX UINT64_MAX
+
+// 7.18.3 Limits of other integer types
+
+#ifdef _WIN64 // [
+# define PTRDIFF_MIN _I64_MIN
+# define PTRDIFF_MAX _I64_MAX
+#else // _WIN64 ][
+# define PTRDIFF_MIN _I32_MIN
+# define PTRDIFF_MAX _I32_MAX
+#endif // _WIN64 ]
+
+#define SIG_ATOMIC_MIN INT_MIN
+#define SIG_ATOMIC_MAX INT_MAX
+
+#ifndef SIZE_MAX // [
+# ifdef _WIN64 // [
+# define SIZE_MAX _UI64_MAX
+# else // _WIN64 ][
+# define SIZE_MAX _UI32_MAX
+# endif // _WIN64 ]
+#endif // SIZE_MAX ]
+
+// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
+#ifndef WCHAR_MIN // [
+# define WCHAR_MIN 0
+#endif // WCHAR_MIN ]
+#ifndef WCHAR_MAX // [
+# define WCHAR_MAX _UI16_MAX
+#endif // WCHAR_MAX ]
+
+#define WINT_MIN 0
+#define WINT_MAX _UI16_MAX
+
+#endif // __STDC_LIMIT_MACROS ]
+
+
+// 7.18.4 Limits of other integer types
+
+#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
+
+// 7.18.4.1 Macros for minimum-width integer constants
+
+#define INT8_C(val) val##i8
+#define INT16_C(val) val##i16
+#define INT32_C(val) val##i32
+//#define INT64_C(val) val##i64
+
+#define UINT8_C(val) val##ui8
+#define UINT16_C(val) val##ui16
+#define UINT32_C(val) val##ui32
+//#define UINT64_C(val) val##ui64
+
+// 7.18.4.2 Macros for greatest-width integer constants
+#define INTMAX_C INT64_C
+#define UINTMAX_C UINT64_C
+
+#endif // __STDC_CONSTANT_MACROS ]
+
+
+#endif // _MSC_STDINT_H_ ]
diff --git a/lib/libhts/Win32/include/sys/queue.h b/lib/libhts/Win32/include/sys/queue.h
new file mode 100644
index 0000000000..5661c71d08
--- /dev/null
+++ b/lib/libhts/Win32/include/sys/queue.h
@@ -0,0 +1,574 @@
+/*
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)queue.h 8.5 (Berkeley) 8/20/94
+ */
+
+#ifndef _SYS_QUEUE_H_
+#define _SYS_QUEUE_H_
+
+/*
+ * This file defines five types of data structures: singly-linked lists,
+ * lists, simple queues, tail queues, and circular queues.
+ *
+ * A singly-linked list is headed by a single forward pointer. The
+ * elements are singly linked for minimum space and pointer manipulation
+ * overhead at the expense of O(n) removal for arbitrary elements. New
+ * elements can be added to the list after an existing element or at the
+ * head of the list. Elements being removed from the head of the list
+ * should use the explicit macro for this purpose for optimum
+ * efficiency. A singly-linked list may only be traversed in the forward
+ * direction. Singly-linked lists are ideal for applications with large
+ * datasets and few or no removals or for implementing a LIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A simple queue is headed by a pair of pointers, one the head of the
+ * list and the other to the tail of the list. The elements are singly
+ * linked to save space, so elements can only be removed from the
+ * head of the list. New elements can be added to the list after
+ * an existing element, at the head of the list, or at the end of the
+ * list. A simple queue may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * A circle queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the list.
+ * A circle queue may be traversed in either direction, but has a more
+ * complex end of list detection.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ */
+
+/*
+ * List definitions.
+ */
+#define LIST_HEAD(name, type) \
+struct name { \
+ struct type *lh_first; /* first element */ \
+}
+
+#define LIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define LIST_ENTRY(type) \
+struct { \
+ struct type *le_next; /* next element */ \
+ struct type **le_prev; /* address of previous next element */ \
+}
+
+/*
+ * List functions.
+ */
+#define LIST_INIT(head) do { \
+ (head)->lh_first = NULL; \
+} while (/*CONSTCOND*/0)
+
+#define LIST_INSERT_AFTER(listelm, elm, field) do { \
+ if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
+ (listelm)->field.le_next->field.le_prev = \
+ &(elm)->field.le_next; \
+ (listelm)->field.le_next = (elm); \
+ (elm)->field.le_prev = &(listelm)->field.le_next; \
+} while (/*CONSTCOND*/0)
+
+#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.le_prev = (listelm)->field.le_prev; \
+ (elm)->field.le_next = (listelm); \
+ *(listelm)->field.le_prev = (elm); \
+ (listelm)->field.le_prev = &(elm)->field.le_next; \
+} while (/*CONSTCOND*/0)
+
+#define LIST_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.le_next = (head)->lh_first) != NULL) \
+ (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
+ (head)->lh_first = (elm); \
+ (elm)->field.le_prev = &(head)->lh_first; \
+} while (/*CONSTCOND*/0)
+
+#define LIST_REMOVE(elm, field) do { \
+ if ((elm)->field.le_next != NULL) \
+ (elm)->field.le_next->field.le_prev = \
+ (elm)->field.le_prev; \
+ *(elm)->field.le_prev = (elm)->field.le_next; \
+} while (/*CONSTCOND*/0)
+
+#define LIST_FOREACH(var, head, field) \
+ for ((var) = ((head)->lh_first); \
+ (var); \
+ (var) = ((var)->field.le_next))
+
+/*
+ * List access methods.
+ */
+#define LIST_EMPTY(head) ((head)->lh_first == NULL)
+#define LIST_FIRST(head) ((head)->lh_first)
+#define LIST_NEXT(elm, field) ((elm)->field.le_next)
+
+
+/*
+ * Singly-linked List definitions.
+ */
+#define SLIST_HEAD(name, type) \
+struct name { \
+ struct type *slh_first; /* first element */ \
+}
+
+#define SLIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define SLIST_ENTRY(type) \
+struct { \
+ struct type *sle_next; /* next element */ \
+}
+
+/*
+ * Singly-linked List functions.
+ */
+#define SLIST_INIT(head) do { \
+ (head)->slh_first = NULL; \
+} while (/*CONSTCOND*/0)
+
+#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
+ (elm)->field.sle_next = (slistelm)->field.sle_next; \
+ (slistelm)->field.sle_next = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define SLIST_INSERT_HEAD(head, elm, field) do { \
+ (elm)->field.sle_next = (head)->slh_first; \
+ (head)->slh_first = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define SLIST_REMOVE_HEAD(head, field) do { \
+ (head)->slh_first = (head)->slh_first->field.sle_next; \
+} while (/*CONSTCOND*/0)
+
+#define SLIST_REMOVE(head, elm, type, field) do { \
+ if ((head)->slh_first == (elm)) { \
+ SLIST_REMOVE_HEAD((head), field); \
+ } \
+ else { \
+ struct type *curelm = (head)->slh_first; \
+ while(curelm->field.sle_next != (elm)) \
+ curelm = curelm->field.sle_next; \
+ curelm->field.sle_next = \
+ curelm->field.sle_next->field.sle_next; \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define SLIST_FOREACH(var, head, field) \
+ for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next)
+
+/*
+ * Singly-linked List access methods.
+ */
+#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
+#define SLIST_FIRST(head) ((head)->slh_first)
+#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
+
+
+/*
+ * Singly-linked Tail queue declarations.
+ */
+#define STAILQ_HEAD(name, type) \
+struct name { \
+ struct type *stqh_first; /* first element */ \
+ struct type **stqh_last; /* addr of last next element */ \
+}
+
+#define STAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).stqh_first }
+
+#define STAILQ_ENTRY(type) \
+struct { \
+ struct type *stqe_next; /* next element */ \
+}
+
+/*
+ * Singly-linked Tail queue functions.
+ */
+#define STAILQ_INIT(head) do { \
+ (head)->stqh_first = NULL; \
+ (head)->stqh_last = &(head)->stqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.stqe_next = (head)->stqh_first) == NULL) \
+ (head)->stqh_last = &(elm)->field.stqe_next; \
+ (head)->stqh_first = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.stqe_next = NULL; \
+ *(head)->stqh_last = (elm); \
+ (head)->stqh_last = &(elm)->field.stqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.stqe_next = (listelm)->field.stqe_next) == NULL)\
+ (head)->stqh_last = &(elm)->field.stqe_next; \
+ (listelm)->field.stqe_next = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_REMOVE_HEAD(head, field) do { \
+ if (((head)->stqh_first = (head)->stqh_first->field.stqe_next) == NULL) \
+ (head)->stqh_last = &(head)->stqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_REMOVE(head, elm, type, field) do { \
+ if ((head)->stqh_first == (elm)) { \
+ STAILQ_REMOVE_HEAD((head), field); \
+ } else { \
+ struct type *curelm = (head)->stqh_first; \
+ while (curelm->field.stqe_next != (elm)) \
+ curelm = curelm->field.stqe_next; \
+ if ((curelm->field.stqe_next = \
+ curelm->field.stqe_next->field.stqe_next) == NULL) \
+ (head)->stqh_last = &(curelm)->field.stqe_next; \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_FOREACH(var, head, field) \
+ for ((var) = ((head)->stqh_first); \
+ (var); \
+ (var) = ((var)->field.stqe_next))
+
+#define STAILQ_CONCAT(head1, head2) do { \
+ if (!STAILQ_EMPTY((head2))) { \
+ *(head1)->stqh_last = (head2)->stqh_first; \
+ (head1)->stqh_last = (head2)->stqh_last; \
+ STAILQ_INIT((head2)); \
+ } \
+} while (/*CONSTCOND*/0)
+
+/*
+ * Singly-linked Tail queue access methods.
+ */
+#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
+#define STAILQ_FIRST(head) ((head)->stqh_first)
+#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
+
+
+/*
+ * Simple queue definitions.
+ */
+#define SIMPLEQ_HEAD(name, type) \
+struct name { \
+ struct type *sqh_first; /* first element */ \
+ struct type **sqh_last; /* addr of last next element */ \
+}
+
+#define SIMPLEQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).sqh_first }
+
+#define SIMPLEQ_ENTRY(type) \
+struct { \
+ struct type *sqe_next; /* next element */ \
+}
+
+/*
+ * Simple queue functions.
+ */
+#define SIMPLEQ_INIT(head) do { \
+ (head)->sqh_first = NULL; \
+ (head)->sqh_last = &(head)->sqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+ (head)->sqh_first = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.sqe_next = NULL; \
+ *(head)->sqh_last = (elm); \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+ (listelm)->field.sqe_next = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_REMOVE_HEAD(head, field) do { \
+ if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
+ (head)->sqh_last = &(head)->sqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_REMOVE(head, elm, type, field) do { \
+ if ((head)->sqh_first == (elm)) { \
+ SIMPLEQ_REMOVE_HEAD((head), field); \
+ } else { \
+ struct type *curelm = (head)->sqh_first; \
+ while (curelm->field.sqe_next != (elm)) \
+ curelm = curelm->field.sqe_next; \
+ if ((curelm->field.sqe_next = \
+ curelm->field.sqe_next->field.sqe_next) == NULL) \
+ (head)->sqh_last = &(curelm)->field.sqe_next; \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_FOREACH(var, head, field) \
+ for ((var) = ((head)->sqh_first); \
+ (var); \
+ (var) = ((var)->field.sqe_next))
+
+/*
+ * Simple queue access methods.
+ */
+#define SIMPLEQ_EMPTY(head) ((head)->sqh_first == NULL)
+#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
+#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
+
+
+/*
+ * Tail queue definitions.
+ */
+#define _TAILQ_HEAD(name, type, qual) \
+struct name { \
+ qual type *tqh_first; /* first element */ \
+ qual type *qual *tqh_last; /* addr of last next element */ \
+}
+#define TAILQ_HEAD(name, type) _TAILQ_HEAD(name, struct type,)
+
+#define TAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).tqh_first }
+
+#define _TAILQ_ENTRY(type, qual) \
+struct { \
+ qual type *tqe_next; /* next element */ \
+ qual type *qual *tqe_prev; /* address of previous next element */\
+}
+#define TAILQ_ENTRY(type) _TAILQ_ENTRY(struct type,)
+
+/*
+ * Tail queue functions.
+ */
+#define TAILQ_INIT(head) do { \
+ (head)->tqh_first = NULL; \
+ (head)->tqh_last = &(head)->tqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
+ (head)->tqh_first->field.tqe_prev = \
+ &(elm)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+ (head)->tqh_first = (elm); \
+ (elm)->field.tqe_prev = &(head)->tqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.tqe_next = NULL; \
+ (elm)->field.tqe_prev = (head)->tqh_last; \
+ *(head)->tqh_last = (elm); \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
+ (elm)->field.tqe_next->field.tqe_prev = \
+ &(elm)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+ (listelm)->field.tqe_next = (elm); \
+ (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
+ (elm)->field.tqe_next = (listelm); \
+ *(listelm)->field.tqe_prev = (elm); \
+ (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_REMOVE(head, elm, field) do { \
+ if (((elm)->field.tqe_next) != NULL) \
+ (elm)->field.tqe_next->field.tqe_prev = \
+ (elm)->field.tqe_prev; \
+ else \
+ (head)->tqh_last = (elm)->field.tqe_prev; \
+ *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_FOREACH(var, head, field) \
+ for ((var) = ((head)->tqh_first); \
+ (var); \
+ (var) = ((var)->field.tqe_next))
+
+#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
+ for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \
+ (var); \
+ (var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last)))
+
+#define TAILQ_CONCAT(head1, head2, field) do { \
+ if (!TAILQ_EMPTY(head2)) { \
+ *(head1)->tqh_last = (head2)->tqh_first; \
+ (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
+ (head1)->tqh_last = (head2)->tqh_last; \
+ TAILQ_INIT((head2)); \
+ } \
+} while (/*CONSTCOND*/0)
+
+/*
+ * Tail queue access methods.
+ */
+#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
+#define TAILQ_FIRST(head) ((head)->tqh_first)
+#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+
+#define TAILQ_LAST(head, headname) \
+ (*(((struct headname *)((head)->tqh_last))->tqh_last))
+#define TAILQ_PREV(elm, headname, field) \
+ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+
+
+/*
+ * Circular queue definitions.
+ */
+#define CIRCLEQ_HEAD(name, type) \
+struct name { \
+ struct type *cqh_first; /* first element */ \
+ struct type *cqh_last; /* last element */ \
+}
+
+#define CIRCLEQ_HEAD_INITIALIZER(head) \
+ { (void *)&head, (void *)&head }
+
+#define CIRCLEQ_ENTRY(type) \
+struct { \
+ struct type *cqe_next; /* next element */ \
+ struct type *cqe_prev; /* previous element */ \
+}
+
+/*
+ * Circular queue functions.
+ */
+#define CIRCLEQ_INIT(head) do { \
+ (head)->cqh_first = (void *)(head); \
+ (head)->cqh_last = (void *)(head); \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ (elm)->field.cqe_next = (listelm)->field.cqe_next; \
+ (elm)->field.cqe_prev = (listelm); \
+ if ((listelm)->field.cqe_next == (void *)(head)) \
+ (head)->cqh_last = (elm); \
+ else \
+ (listelm)->field.cqe_next->field.cqe_prev = (elm); \
+ (listelm)->field.cqe_next = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
+ (elm)->field.cqe_next = (listelm); \
+ (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
+ if ((listelm)->field.cqe_prev == (void *)(head)) \
+ (head)->cqh_first = (elm); \
+ else \
+ (listelm)->field.cqe_prev->field.cqe_next = (elm); \
+ (listelm)->field.cqe_prev = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
+ (elm)->field.cqe_next = (head)->cqh_first; \
+ (elm)->field.cqe_prev = (void *)(head); \
+ if ((head)->cqh_last == (void *)(head)) \
+ (head)->cqh_last = (elm); \
+ else \
+ (head)->cqh_first->field.cqe_prev = (elm); \
+ (head)->cqh_first = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.cqe_next = (void *)(head); \
+ (elm)->field.cqe_prev = (head)->cqh_last; \
+ if ((head)->cqh_first == (void *)(head)) \
+ (head)->cqh_first = (elm); \
+ else \
+ (head)->cqh_last->field.cqe_next = (elm); \
+ (head)->cqh_last = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_REMOVE(head, elm, field) do { \
+ if ((elm)->field.cqe_next == (void *)(head)) \
+ (head)->cqh_last = (elm)->field.cqe_prev; \
+ else \
+ (elm)->field.cqe_next->field.cqe_prev = \
+ (elm)->field.cqe_prev; \
+ if ((elm)->field.cqe_prev == (void *)(head)) \
+ (head)->cqh_first = (elm)->field.cqe_next; \
+ else \
+ (elm)->field.cqe_prev->field.cqe_next = \
+ (elm)->field.cqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_FOREACH(var, head, field) \
+ for ((var) = ((head)->cqh_first); \
+ (var) != (const void *)(head); \
+ (var) = ((var)->field.cqe_next))
+
+#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
+ for ((var) = ((head)->cqh_last); \
+ (var) != (const void *)(head); \
+ (var) = ((var)->field.cqe_prev))
+
+/*
+ * Circular queue access methods.
+ */
+#define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head))
+#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
+#define CIRCLEQ_LAST(head) ((head)->cqh_last)
+#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
+#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
+
+#define CIRCLEQ_LOOP_NEXT(head, elm, field) \
+ (((elm)->field.cqe_next == (void *)(head)) \
+ ? ((head)->cqh_first) \
+ : (elm->field.cqe_next))
+#define CIRCLEQ_LOOP_PREV(head, elm, field) \
+ (((elm)->field.cqe_prev == (void *)(head)) \
+ ? ((head)->cqh_last) \
+ : (elm->field.cqe_prev))
+
+#endif /* sys/queue.h */ \ No newline at end of file
diff --git a/lib/libhts/Win32/include/unistd.h b/lib/libhts/Win32/include/unistd.h
new file mode 100644
index 0000000000..4799c2bffe
--- /dev/null
+++ b/lib/libhts/Win32/include/unistd.h
@@ -0,0 +1,47 @@
+/*
+ * This file is part of the Mingw32 package.
+ *
+ * unistd.h maps (roughly) to io.h
+ */
+
+#ifndef _UNISTD_H
+#define _UNISTD_H
+
+#include <io.h>
+#include <process.h>
+
+#define __UNISTD_GETOPT__
+#include <getopt.h>
+#undef __UNISTD_GETOPT__
+
+/* These are also defined in stdio.h. */
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif
+
+#ifndef SEEK_CUR
+#define SEEK_CUR 1
+#endif
+
+#ifndef SEEK_END
+#define SEEK_END 2
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* This is defined as a real library function to allow autoconf
+ to verify its existence. */
+//int ftruncate(int, off_t);
+//__CRT_INLINE int ftruncate(int __fd, off_t __length)
+//{
+// return _chsize (__fd, __length);
+//}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _UNISTD_H */
diff --git a/lib/libhts/Win32/libhts_2003.sln b/lib/libhts/Win32/libhts_2003.sln
new file mode 100644
index 0000000000..99b09b3843
--- /dev/null
+++ b/lib/libhts/Win32/libhts_2003.sln
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libhts_2003", "libhts_2003.vcproj", "{870DE8D3-B710-4CEF-9C73-36B37A9AF8A3}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ Debug = Debug
+ Release = Release
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {870DE8D3-B710-4CEF-9C73-36B37A9AF8A3}.Debug.ActiveCfg = Debug|Win32
+ {870DE8D3-B710-4CEF-9C73-36B37A9AF8A3}.Debug.Build.0 = Debug|Win32
+ {870DE8D3-B710-4CEF-9C73-36B37A9AF8A3}.Release.ActiveCfg = Release|Win32
+ {870DE8D3-B710-4CEF-9C73-36B37A9AF8A3}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/lib/libhts/Win32/libhts_2003.vcproj b/lib/libhts/Win32/libhts_2003.vcproj
new file mode 100644
index 0000000000..917387735b
--- /dev/null
+++ b/lib/libhts/Win32/libhts_2003.vcproj
@@ -0,0 +1,161 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="libhts_2003"
+ ProjectGUID="{870DE8D3-B710-4CEF-9C73-36B37A9AF8A3}"
+ RootNamespace="libhts_2003"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="4"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="&quot;$(ProjectDir)include&quot;"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="$(OutDir)/libhts_2003.lib"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="4"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="&quot;$(ProjectDir)include&quot;"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="$(OutDir)/libhts_2003.lib"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+ <File
+ RelativePath="..\config.h">
+ </File>
+ <File
+ RelativePath="..\hts_strtab.h">
+ </File>
+ <File
+ RelativePath="..\htsatomic.c">
+ </File>
+ <File
+ RelativePath="..\htsatomic.h">
+ </File>
+ <File
+ RelativePath="..\htsbuf.c">
+ </File>
+ <File
+ RelativePath="..\htsbuf.h">
+ </File>
+ <File
+ RelativePath="..\htsmsg.c">
+ </File>
+ <File
+ RelativePath="..\htsmsg.h">
+ </File>
+ <File
+ RelativePath="..\htsmsg_binary.c">
+ </File>
+ <File
+ RelativePath="..\htsmsg_binary.h">
+ </File>
+ <File
+ RelativePath="..\htsq.h">
+ </File>
+ <File
+ RelativePath="..\htsstr.c">
+ </File>
+ <File
+ RelativePath="..\htsstr.h">
+ </File>
+ <File
+ RelativePath="..\htsthreads.h">
+ </File>
+ <File
+ RelativePath="..\net.h">
+ </File>
+ <File
+ RelativePath="..\net_winsock.c">
+ </File>
+ <File
+ RelativePath="..\sha1.c">
+ </File>
+ <File
+ RelativePath="..\sha1.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/lib/libhts/Win32/libhts_2008.sln b/lib/libhts/Win32/libhts_2008.sln
new file mode 100644
index 0000000000..f2fb0a067d
--- /dev/null
+++ b/lib/libhts/Win32/libhts_2008.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libhts", "libhts_2008.vcproj", "{00700E12-A63B-4E54-B962-4011A90584BD}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {00700E12-A63B-4E54-B962-4011A90584BD}.Debug|Win32.ActiveCfg = Debug|Win32
+ {00700E12-A63B-4E54-B962-4011A90584BD}.Debug|Win32.Build.0 = Debug|Win32
+ {00700E12-A63B-4E54-B962-4011A90584BD}.Release|Win32.ActiveCfg = Release|Win32
+ {00700E12-A63B-4E54-B962-4011A90584BD}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/lib/libhts/Win32/libhts_2008.vcproj b/lib/libhts/Win32/libhts_2008.vcproj
new file mode 100644
index 0000000000..ecbbe616c9
--- /dev/null
+++ b/lib/libhts/Win32/libhts_2008.vcproj
@@ -0,0 +1,237 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="libhts"
+ ProjectGUID="{00700E12-A63B-4E54-B962-4011A90584BD}"
+ RootNamespace="libhts"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)libs\$(ProjectName)\$(ConfigurationName)\"
+ IntermediateDirectory="$(SolutionDir)objs\$(ProjectName)\$(ConfigurationName)\"
+ ConfigurationType="4"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="&quot;$(ProjectDir)include&quot;"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="0"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ IgnoreAllDefaultLibraries="true"
+ IgnoreDefaultLibraryNames=""
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)libs\$(ProjectName)\$(ConfigurationName)\"
+ IntermediateDirectory="$(SolutionDir)objs\$(ProjectName)\$(ConfigurationName)\"
+ ConfigurationType="4"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ AdditionalIncludeDirectories="&quot;$(ProjectDir)include&quot;"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ IgnoreAllDefaultLibraries="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\config.h"
+ >
+ </File>
+ <File
+ RelativePath="..\hts_strtab.h"
+ >
+ </File>
+ <File
+ RelativePath="..\htsatomic.c"
+ >
+ </File>
+ <File
+ RelativePath="..\htsatomic.h"
+ >
+ </File>
+ <File
+ RelativePath="..\htsbuf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\htsbuf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\htsmsg.c"
+ >
+ </File>
+ <File
+ RelativePath="..\htsmsg.h"
+ >
+ </File>
+ <File
+ RelativePath="..\htsmsg_binary.c"
+ >
+ </File>
+ <File
+ RelativePath="..\htsmsg_binary.h"
+ >
+ </File>
+ <File
+ RelativePath="..\htsq.h"
+ >
+ </File>
+ <File
+ RelativePath="..\htsstr.c"
+ >
+ </File>
+ <File
+ RelativePath="..\htsstr.h"
+ >
+ </File>
+ <File
+ RelativePath="..\htsthreads.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\msvc.h"
+ >
+ </File>
+ <File
+ RelativePath="..\net.h"
+ >
+ </File>
+ <File
+ RelativePath="..\net_winsock.c"
+ >
+ </File>
+ <File
+ RelativePath="..\sha1.c"
+ >
+ </File>
+ <File
+ RelativePath="..\sha1.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/lib/libhts/Win32/libhts_2010.vcxproj b/lib/libhts/Win32/libhts_2010.vcxproj
new file mode 100644
index 0000000000..d15bf12df6
--- /dev/null
+++ b/lib/libhts/Win32/libhts_2010.vcxproj
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.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="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectName>libhts</ProjectName>
+ <ProjectGuid>{00700E12-A63B-4E54-B962-4011A90584BD}</ProjectGuid>
+ <RootNamespace>libhts</RootNamespace>
+ <Keyword>Win32Proj</Keyword>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </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" />
+ <Import Project="..\..\..\project\VS2010Express\XBMC for Windows.props" />
+ </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" />
+ <Import Project="..\..\..\project\VS2010Express\XBMC for Windows.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)libs\$(TargetName)\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)objs\$(TargetName)\$(Configuration)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)libs\$(TargetName)\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)objs\$(TargetName)\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>$(ProjectDir)include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>Default</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ </ClCompile>
+ <Lib>
+ <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+ <IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>$(ProjectDir)include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Lib>
+ <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="..\hts_strtab.h" />
+ <ClInclude Include="..\htsatomic.h" />
+ <ClInclude Include="..\htsbuf.h" />
+ <ClInclude Include="..\htsmsg.h" />
+ <ClInclude Include="..\htsmsg_binary.h" />
+ <ClInclude Include="..\htsq.h" />
+ <ClInclude Include="..\htsstr.h" />
+ <ClInclude Include="include\msvc.h" />
+ <ClInclude Include="..\net.h" />
+ <ClInclude Include="..\sha1.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\htsatomic.c" />
+ <ClCompile Include="..\htsbuf.c" />
+ <ClCompile Include="..\htsmsg.c" />
+ <ClCompile Include="..\htsmsg_binary.c" />
+ <ClCompile Include="..\htsstr.c" />
+ <ClCompile Include="..\net_winsock.c" />
+ <ClCompile Include="..\sha1.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/lib/libhts/Win32/libhts_2010.vcxproj.filters b/lib/libhts/Win32/libhts_2010.vcxproj.filters
new file mode 100644
index 0000000000..a4be5cadf0
--- /dev/null
+++ b/lib/libhts/Win32/libhts_2010.vcxproj.filters
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\hts_strtab.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\htsatomic.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\htsbuf.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\htsmsg.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\htsmsg_binary.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\htsq.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\htsstr.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ <ClInclude Include="include\msvc.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\net.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\sha1.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\htsatomic.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\htsbuf.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\htsmsg.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\htsmsg_binary.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\htsstr.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\net_winsock.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\sha1.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/lib/libhts/hts_strtab.h b/lib/libhts/hts_strtab.h
new file mode 100644
index 0000000000..706c611da6
--- /dev/null
+++ b/lib/libhts/hts_strtab.h
@@ -0,0 +1,61 @@
+/*
+ * tvheadend
+ * Copyright (C) 2007 Andreas Öman
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef STRTAB_H_
+#define STRTAB_H_
+
+#include <strings.h>
+
+struct strtab {
+ const char *str;
+ int val;
+};
+
+static int str2val0(const char *str, struct strtab tab[], int l)
+ __attribute((unused));
+
+static int
+str2val0(const char *str, struct strtab tab[], int l)
+{
+ int i;
+ for(i = 0; i < l; i++)
+ if(!strcasecmp(str, tab[i].str))
+ return tab[i].val;
+
+ return -1;
+}
+
+#define str2val(str, tab) str2val0(str, tab, sizeof(tab) / sizeof(tab[0]))
+
+static const char * val2str0(int val, struct strtab tab[], int l)
+ __attribute__((unused));
+
+static const char *
+val2str0(int val, struct strtab tab[], int l)
+{
+ int i;
+ for(i = 0; i < l; i++)
+ if(tab[i].val == val)
+ return tab[i].str;
+ return NULL;
+}
+
+#define val2str(val, tab) val2str0(val, tab, sizeof(tab) / sizeof(tab[0]))
+
+#endif /* STRTAB_H_ */
diff --git a/lib/libhts/htsatomic.c b/lib/libhts/htsatomic.c
new file mode 100644
index 0000000000..8583b4e89d
--- /dev/null
+++ b/lib/libhts/htsatomic.c
@@ -0,0 +1,19 @@
+/*
+ * Atomic ops
+ * Copyright (C) 2008 Andreas Öman
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+/* Nothing here yet */
diff --git a/lib/libhts/htsatomic.h b/lib/libhts/htsatomic.h
new file mode 100644
index 0000000000..62fb5f8fc6
--- /dev/null
+++ b/lib/libhts/htsatomic.h
@@ -0,0 +1,37 @@
+/*
+ * Atomic ops
+ * Copyright (C) 2008 Andreas Öman
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef HTSATOMIC_H__
+#define HTSATOMIC_H__
+
+/**
+ * Atomically add 'incr' to *ptr and return the previous value
+ */
+#if defined(__i386__) || defined(__x86_64__)
+static inline int
+atomic_add(volatile int *ptr, int incr)
+{
+ int r;
+ asm volatile("lock; xaddl %0, %1" :
+ "=r"(r), "=m"(*ptr) : "0" (incr), "m" (*ptr) : "memory");
+ return r;
+}
+#endif
+
+#endif /* HTSATOMIC_H__ */
diff --git a/lib/libhts/htsbuf.c b/lib/libhts/htsbuf.c
new file mode 100644
index 0000000000..09ec334486
--- /dev/null
+++ b/lib/libhts/htsbuf.c
@@ -0,0 +1,255 @@
+/*
+ * Buffer management functions
+ * Copyright (C) 2008 Andreas Öman
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include "htsbuf.h"
+#ifdef _MSC_VER
+#include "msvc.h"
+#endif
+
+#ifndef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef MAX
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#endif
+
+
+/**
+ *
+ */
+void
+htsbuf_queue_init(htsbuf_queue_t *hq, unsigned int maxsize)
+{
+ if(maxsize == 0)
+ maxsize = INT32_MAX;
+ TAILQ_INIT(&hq->hq_q);
+ hq->hq_size = 0;
+ hq->hq_maxsize = maxsize;
+}
+
+
+/**
+ *
+ */
+void
+htsbuf_data_free(htsbuf_queue_t *hq, htsbuf_data_t *hd)
+{
+ TAILQ_REMOVE(&hq->hq_q, hd, hd_link);
+ free(hd->hd_data);
+ free(hd);
+}
+
+
+/**
+ *
+ */
+void
+htsbuf_queue_flush(htsbuf_queue_t *hq)
+{
+ htsbuf_data_t *hd;
+
+ hq->hq_size = 0;
+
+ while((hd = TAILQ_FIRST(&hq->hq_q)) != NULL)
+ htsbuf_data_free(hq, hd);
+}
+
+/**
+ *
+ */
+void
+htsbuf_append(htsbuf_queue_t *hq, const char *buf, size_t len)
+{
+ htsbuf_data_t *hd = TAILQ_LAST(&hq->hq_q, htsbuf_data_queue);
+ int c;
+ hq->hq_size += len;
+
+ if(hd != NULL) {
+ /* Fill out any previous buffer */
+ c = MIN(hd->hd_data_size - hd->hd_data_len, len);
+ memcpy(hd->hd_data + hd->hd_data_len, buf, c);
+ hd->hd_data_len += c;
+ buf += c;
+ len -= c;
+ }
+ if(len == 0)
+ return;
+
+ hd = malloc(sizeof(htsbuf_data_t));
+ TAILQ_INSERT_TAIL(&hq->hq_q, hd, hd_link);
+
+ c = MAX(len, 1000); /* Allocate 1000 bytes to support lots of small writes */
+
+ hd->hd_data = malloc(c);
+ hd->hd_data_size = c;
+ hd->hd_data_len = len;
+ hd->hd_data_off = 0;
+ memcpy(hd->hd_data, buf, len);
+}
+
+/**
+ *
+ */
+void
+htsbuf_append_prealloc(htsbuf_queue_t *hq, const char *buf, size_t len)
+{
+ htsbuf_data_t *hd;
+
+ hq->hq_size += len;
+
+ hd = malloc(sizeof(htsbuf_data_t));
+ TAILQ_INSERT_TAIL(&hq->hq_q, hd, hd_link);
+
+ hd->hd_data = (void *)buf;
+ hd->hd_data_size = len;
+ hd->hd_data_len = len;
+ hd->hd_data_off = 0;
+}
+
+/**
+ *
+ */
+size_t
+htsbuf_read(htsbuf_queue_t *hq, char *buf, size_t len)
+{
+ size_t r = 0;
+ int c;
+
+ htsbuf_data_t *hd;
+
+ while(len > 0) {
+ hd = TAILQ_FIRST(&hq->hq_q);
+ if(hd == NULL)
+ break;
+
+ c = MIN(hd->hd_data_len - hd->hd_data_off, len);
+ memcpy(buf, hd->hd_data + hd->hd_data_off, c);
+
+ r += c;
+ buf += c;
+ len -= c;
+ hd->hd_data_off += c;
+ hq->hq_size -= c;
+ if(hd->hd_data_off == hd->hd_data_len)
+ htsbuf_data_free(hq, hd);
+ }
+ return r;
+}
+
+
+/**
+ *
+ */
+size_t
+htsbuf_find(htsbuf_queue_t *hq, uint8_t v)
+{
+ htsbuf_data_t *hd;
+ unsigned int i, o = 0;
+
+ TAILQ_FOREACH(hd, &hq->hq_q, hd_link) {
+ for(i = hd->hd_data_off; i < hd->hd_data_len; i++) {
+ if(hd->hd_data[i] == v)
+ return o + i - hd->hd_data_off;
+ }
+ o += hd->hd_data_len - hd->hd_data_off;
+ }
+ return -1;
+}
+
+
+
+/**
+ *
+ */
+size_t
+htsbuf_peek(htsbuf_queue_t *hq, char *buf, size_t len)
+{
+ size_t r = 0;
+ int c;
+
+ htsbuf_data_t *hd = TAILQ_FIRST(&hq->hq_q);
+
+ while(len > 0 && hd != NULL) {
+ c = MIN(hd->hd_data_len - hd->hd_data_off, len);
+ memcpy(buf, hd->hd_data + hd->hd_data_off, c);
+
+ buf += c;
+ len -= c;
+
+ hd = TAILQ_NEXT(hd, hd_link);
+ }
+ return r;
+}
+
+/**
+ *
+ */
+size_t
+htsbuf_drop(htsbuf_queue_t *hq, size_t len)
+{
+ size_t r = 0;
+ int c;
+ htsbuf_data_t *hd;
+
+ while(len > 0) {
+ hd = TAILQ_FIRST(&hq->hq_q);
+ if(hd == NULL)
+ break;
+
+ c = MIN(hd->hd_data_len - hd->hd_data_off, len);
+ len -= c;
+ hd->hd_data_off += c;
+
+ if(hd->hd_data_off == hd->hd_data_len)
+ htsbuf_data_free(hq, hd);
+ }
+ return r;
+}
+
+/**
+ *
+ */
+void
+htsbuf_vqprintf(htsbuf_queue_t *hq, const char *fmt, va_list ap)
+{
+ char buf[5000];
+ htsbuf_append(hq, buf, vsnprintf(buf, sizeof(buf), fmt, ap));
+}
+
+
+/**
+ *
+ */
+void
+htsbuf_qprintf(htsbuf_queue_t *hq, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ htsbuf_vqprintf(hq, fmt, ap);
+ va_end(ap);
+}
+
+
diff --git a/lib/libhts/htsbuf.h b/lib/libhts/htsbuf.h
new file mode 100644
index 0000000000..2ef22100ba
--- /dev/null
+++ b/lib/libhts/htsbuf.h
@@ -0,0 +1,65 @@
+/*
+ * Buffer management functions
+ * Copyright (C) 2008 Andreas Öman
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef HTSBUF_H__
+#define HTSBUF_H__
+
+#include <stdarg.h>
+#include "htsq.h"
+#include <inttypes.h>
+
+TAILQ_HEAD(htsbuf_data_queue, htsbuf_data);
+
+typedef struct htsbuf_data {
+ TAILQ_ENTRY(htsbuf_data) hd_link;
+ uint8_t *hd_data;
+ unsigned int hd_data_size; /* Size of allocation hb_data */
+ unsigned int hd_data_len; /* Number of valid bytes from hd_data */
+ unsigned int hd_data_off; /* Offset in data, used for partial writes */
+} htsbuf_data_t;
+
+typedef struct htsbuf_queue {
+ struct htsbuf_data_queue hq_q;
+ unsigned int hq_size;
+ unsigned int hq_maxsize;
+} htsbuf_queue_t;
+
+void htsbuf_queue_init(htsbuf_queue_t *hq, unsigned int maxsize);
+
+void htsbuf_queue_flush(htsbuf_queue_t *hq);
+
+void htsbuf_vqprintf(htsbuf_queue_t *hq, const char *fmt, va_list ap);
+
+void htsbuf_qprintf(htsbuf_queue_t *hq, const char *fmt, ...);
+
+void htsbuf_append(htsbuf_queue_t *hq, const char *buf, size_t len);
+
+void htsbuf_append_prealloc(htsbuf_queue_t *hq, const char *buf, size_t len);
+
+void htsbuf_data_free(htsbuf_queue_t *hq, htsbuf_data_t *hd);
+
+size_t htsbuf_read(htsbuf_queue_t *hq, char *buf, size_t len);
+
+size_t htsbuf_peek(htsbuf_queue_t *hq, char *buf, size_t len);
+
+size_t htsbuf_drop(htsbuf_queue_t *hq, size_t len);
+
+size_t htsbuf_find(htsbuf_queue_t *hq, uint8_t v);
+
+#endif /* HTSBUF_H__ */
diff --git a/lib/libhts/htsmsg.c b/lib/libhts/htsmsg.c
new file mode 100644
index 0000000000..3d5c316d02
--- /dev/null
+++ b/lib/libhts/htsmsg.c
@@ -0,0 +1,578 @@
+/*
+ * Functions for manipulating HTS messages
+ * Copyright (C) 2007 Andreas Öman
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <assert.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#ifdef _MSC_VER
+#include "msvc.h"
+#endif
+
+#include "htsmsg.h"
+
+static void htsmsg_clear(htsmsg_t *msg);
+
+/*
+ *
+ */
+static void
+htsmsg_field_destroy(htsmsg_t *msg, htsmsg_field_t *f)
+{
+ TAILQ_REMOVE(&msg->hm_fields, f, hmf_link);
+
+ switch(f->hmf_type) {
+ case HMF_MAP:
+ case HMF_LIST:
+ htsmsg_clear(&f->hmf_msg);
+ break;
+
+ case HMF_STR:
+ if(f->hmf_flags & HMF_ALLOCED)
+ free((void *)f->hmf_str);
+ break;
+
+ case HMF_BIN:
+ if(f->hmf_flags & HMF_ALLOCED)
+ free((void *)f->hmf_bin);
+ break;
+ default:
+ break;
+ }
+ if(f->hmf_flags & HMF_NAME_ALLOCED)
+ free((void *)f->hmf_name);
+ free(f);
+}
+
+/*
+ *
+ */
+static void
+htsmsg_clear(htsmsg_t *msg)
+{
+ htsmsg_field_t *f;
+
+ while((f = TAILQ_FIRST(&msg->hm_fields)) != NULL)
+ htsmsg_field_destroy(msg, f);
+}
+
+
+
+/*
+ *
+ */
+htsmsg_field_t *
+htsmsg_field_add(htsmsg_t *msg, const char *name, int type, int flags)
+{
+ htsmsg_field_t *f = malloc(sizeof(htsmsg_field_t));
+
+ TAILQ_INSERT_TAIL(&msg->hm_fields, f, hmf_link);
+
+ if(msg->hm_islist) {
+ assert(name == NULL);
+ } else {
+ assert(name != NULL);
+ }
+
+ if(flags & HMF_NAME_ALLOCED)
+ f->hmf_name = name ? strdup(name) : NULL;
+ else
+ f->hmf_name = name;
+
+ f->hmf_type = type;
+ f->hmf_flags = flags;
+ return f;
+}
+
+
+/*
+ *
+ */
+static htsmsg_field_t *
+htsmsg_field_find(htsmsg_t *msg, const char *name)
+{
+ htsmsg_field_t *f;
+
+ TAILQ_FOREACH(f, &msg->hm_fields, hmf_link) {
+ if(f->hmf_name != NULL && !strcmp(f->hmf_name, name))
+ return f;
+ }
+ return NULL;
+}
+
+
+
+/**
+ *
+ */
+int
+htsmsg_delete_field(htsmsg_t *msg, const char *name)
+{
+ htsmsg_field_t *f;
+
+ if((f = htsmsg_field_find(msg, name)) == NULL)
+ return HTSMSG_ERR_FIELD_NOT_FOUND;
+ htsmsg_field_destroy(msg, f);
+ return 0;
+}
+
+
+/*
+ *
+ */
+htsmsg_t *
+htsmsg_create_map(void)
+{
+ htsmsg_t *msg;
+
+ msg = malloc(sizeof(htsmsg_t));
+ TAILQ_INIT(&msg->hm_fields);
+ msg->hm_data = NULL;
+ msg->hm_islist = 0;
+ return msg;
+}
+
+/*
+ *
+ */
+htsmsg_t *
+htsmsg_create_list(void)
+{
+ htsmsg_t *msg;
+
+ msg = malloc(sizeof(htsmsg_t));
+ TAILQ_INIT(&msg->hm_fields);
+ msg->hm_data = NULL;
+ msg->hm_islist = 1;
+ return msg;
+}
+
+
+/*
+ *
+ */
+void
+htsmsg_destroy(htsmsg_t *msg)
+{
+ if(msg == NULL)
+ return;
+
+ htsmsg_clear(msg);
+ free((void *)msg->hm_data);
+ free(msg);
+}
+
+/*
+ *
+ */
+void
+htsmsg_add_u32(htsmsg_t *msg, const char *name, uint32_t u32)
+{
+ htsmsg_field_t *f = htsmsg_field_add(msg, name, HMF_S64, HMF_NAME_ALLOCED);
+ f->hmf_s64 = u32;
+}
+
+/*
+ *
+ */
+void
+htsmsg_add_s64(htsmsg_t *msg, const char *name, int64_t s64)
+{
+ htsmsg_field_t *f = htsmsg_field_add(msg, name, HMF_S64, HMF_NAME_ALLOCED);
+ f->hmf_s64 = s64;
+}
+
+/*
+ *
+ */
+void
+htsmsg_add_s32(htsmsg_t *msg, const char *name, int32_t s32)
+{
+ htsmsg_field_t *f = htsmsg_field_add(msg, name, HMF_S64, HMF_NAME_ALLOCED);
+ f->hmf_s64 = s32;
+}
+
+
+
+/*
+ *
+ */
+void
+htsmsg_add_str(htsmsg_t *msg, const char *name, const char *str)
+{
+ htsmsg_field_t *f = htsmsg_field_add(msg, name, HMF_STR,
+ HMF_ALLOCED | HMF_NAME_ALLOCED);
+ f->hmf_str = strdup(str);
+}
+
+/*
+ *
+ */
+void
+htsmsg_add_bin(htsmsg_t *msg, const char *name, const void *bin, size_t len)
+{
+ htsmsg_field_t *f = htsmsg_field_add(msg, name, HMF_BIN,
+ HMF_ALLOCED | HMF_NAME_ALLOCED);
+ void *v;
+ f->hmf_bin = v = malloc(len);
+ f->hmf_binsize = len;
+ memcpy(v, bin, len);
+}
+
+/*
+ *
+ */
+void
+htsmsg_add_binptr(htsmsg_t *msg, const char *name, const void *bin, size_t len)
+{
+ htsmsg_field_t *f = htsmsg_field_add(msg, name, HMF_BIN, HMF_NAME_ALLOCED);
+ f->hmf_bin = bin;
+ f->hmf_binsize = len;
+}
+
+
+/*
+ *
+ */
+void
+htsmsg_add_msg(htsmsg_t *msg, const char *name, htsmsg_t *sub)
+{
+ htsmsg_field_t *f;
+
+ f = htsmsg_field_add(msg, name, sub->hm_islist ? HMF_LIST : HMF_MAP,
+ HMF_NAME_ALLOCED);
+
+ assert(sub->hm_data == NULL);
+ TAILQ_MOVE(&f->hmf_msg.hm_fields, &sub->hm_fields, hmf_link);
+ free(sub);
+}
+
+
+
+/*
+ *
+ */
+void
+htsmsg_add_msg_extname(htsmsg_t *msg, const char *name, htsmsg_t *sub)
+{
+ htsmsg_field_t *f;
+
+ f = htsmsg_field_add(msg, name, sub->hm_islist ? HMF_LIST : HMF_MAP, 0);
+
+ assert(sub->hm_data == NULL);
+ TAILQ_MOVE(&f->hmf_msg.hm_fields, &sub->hm_fields, hmf_link);
+ free(sub);
+}
+
+
+
+/**
+ *
+ */
+int
+htsmsg_get_s64(htsmsg_t *msg, const char *name, int64_t *s64p)
+{
+ htsmsg_field_t *f;
+
+ if((f = htsmsg_field_find(msg, name)) == NULL)
+ return HTSMSG_ERR_FIELD_NOT_FOUND;
+
+ switch(f->hmf_type) {
+ default:
+ return HTSMSG_ERR_CONVERSION_IMPOSSIBLE;
+ case HMF_STR:
+ *s64p = strtoll(f->hmf_str, NULL, 0);
+ break;
+ case HMF_S64:
+ *s64p = f->hmf_s64;
+ break;
+ }
+ return 0;
+}
+
+
+/*
+ *
+ */
+int
+htsmsg_get_u32(htsmsg_t *msg, const char *name, uint32_t *u32p)
+{
+ int r;
+ int64_t s64;
+
+ if((r = htsmsg_get_s64(msg, name, &s64)) != 0)
+ return r;
+
+ if(s64 < 0 || s64 > 0xffffffffLL)
+ return HTSMSG_ERR_CONVERSION_IMPOSSIBLE;
+
+ *u32p = (uint32_t)s64;
+ return 0;
+}
+
+/**
+ *
+ */
+int
+htsmsg_get_u32_or_default(htsmsg_t *msg, const char *name, uint32_t def)
+{
+ uint32_t u32;
+ return htsmsg_get_u32(msg, name, &u32) ? def : u32;
+}
+
+
+
+/*
+ *
+ */
+int
+htsmsg_get_s32(htsmsg_t *msg, const char *name, int32_t *s32p)
+{
+ int r;
+ int64_t s64;
+
+ if((r = htsmsg_get_s64(msg, name, &s64)) != 0)
+ return r;
+
+ if(s64 < -0x80000000LL || s64 > 0x7fffffffLL)
+ return HTSMSG_ERR_CONVERSION_IMPOSSIBLE;
+
+ *s32p = (int32_t)s64;
+ return 0;
+}
+
+
+/*
+ *
+ */
+int
+htsmsg_get_bin(htsmsg_t *msg, const char *name, const void **binp,
+ size_t *lenp)
+{
+ htsmsg_field_t *f;
+
+ if((f = htsmsg_field_find(msg, name)) == NULL)
+ return HTSMSG_ERR_FIELD_NOT_FOUND;
+
+ if(f->hmf_type != HMF_BIN)
+ return HTSMSG_ERR_CONVERSION_IMPOSSIBLE;
+
+ *binp = f->hmf_bin;
+ *lenp = f->hmf_binsize;
+ return 0;
+}
+
+/**
+ *
+ */
+const char *
+htsmsg_field_get_string(htsmsg_field_t *f)
+{
+ char buf[40];
+
+ switch(f->hmf_type) {
+ default:
+ return NULL;
+ case HMF_STR:
+ break;
+ case HMF_S64:
+ snprintf(buf, sizeof(buf), "%"PRId64, f->hmf_s64);
+ f->hmf_str = strdup(buf);
+ f->hmf_type = HMF_STR;
+ break;
+ }
+ return f->hmf_str;
+}
+
+/*
+ *
+ */
+const char *
+htsmsg_get_str(htsmsg_t *msg, const char *name)
+{
+ htsmsg_field_t *f;
+
+ if((f = htsmsg_field_find(msg, name)) == NULL)
+ return NULL;
+ return htsmsg_field_get_string(f);
+
+}
+
+/*
+ *
+ */
+htsmsg_t *
+htsmsg_get_map(htsmsg_t *msg, const char *name)
+{
+ htsmsg_field_t *f;
+
+ if((f = htsmsg_field_find(msg, name)) == NULL || f->hmf_type != HMF_MAP)
+ return NULL;
+
+ return &f->hmf_msg;
+}
+
+/**
+ *
+ */
+htsmsg_t *
+htsmsg_get_map_multi(htsmsg_t *msg, ...)
+{
+ va_list ap;
+ const char *n;
+ va_start(ap, msg);
+
+ while(msg != NULL && (n = va_arg(ap, char *)) != NULL)
+ msg = htsmsg_get_map(msg, n);
+ return msg;
+}
+
+/*
+ *
+ */
+htsmsg_t *
+htsmsg_get_list(htsmsg_t *msg, const char *name)
+{
+ htsmsg_field_t *f;
+
+ if((f = htsmsg_field_find(msg, name)) == NULL || f->hmf_type != HMF_LIST)
+ return NULL;
+
+ return &f->hmf_msg;
+}
+
+/**
+ *
+ */
+htsmsg_t *
+htsmsg_detach_submsg(htsmsg_field_t *f)
+{
+ htsmsg_t *r = htsmsg_create_map();
+
+ TAILQ_MOVE(&r->hm_fields, &f->hmf_msg.hm_fields, hmf_link);
+ TAILQ_INIT(&f->hmf_msg.hm_fields);
+ r->hm_islist = f->hmf_type == HMF_LIST;
+ return r;
+}
+
+
+/*
+ *
+ */
+static void
+htsmsg_print0(htsmsg_t *msg, int indent)
+{
+ htsmsg_field_t *f;
+ int i;
+
+ TAILQ_FOREACH(f, &msg->hm_fields, hmf_link) {
+
+ for(i = 0; i < indent; i++) printf("\t");
+
+ printf("%s (", f->hmf_name ? f->hmf_name : "");
+
+ switch(f->hmf_type) {
+
+ case HMF_MAP:
+ printf("MAP) = {\n");
+ htsmsg_print0(&f->hmf_msg, indent + 1);
+ for(i = 0; i < indent; i++) printf("\t"); printf("}\n");
+ break;
+
+ case HMF_LIST:
+ printf("LIST) = {\n");
+ htsmsg_print0(&f->hmf_msg, indent + 1);
+ for(i = 0; i < indent; i++) printf("\t"); printf("}\n");
+ break;
+
+ case HMF_STR:
+ printf("STR) = \"%s\"\n", f->hmf_str);
+ break;
+
+ case HMF_BIN:
+ printf("BIN) = [");
+ for(i = 0; i < (int)f->hmf_binsize - 1; i++)
+ printf("%02x.", ((uint8_t *)f->hmf_bin)[i]);
+ printf("%02x]\n", ((uint8_t *)f->hmf_bin)[i]);
+ break;
+
+ case HMF_S64:
+ printf("S64) = %" PRId64 "\n", f->hmf_s64);
+ break;
+ }
+ }
+}
+
+/*
+ *
+ */
+void
+htsmsg_print(htsmsg_t *msg)
+{
+ htsmsg_print0(msg, 0);
+}
+
+
+/**
+ *
+ */
+static void
+htsmsg_copy_i(htsmsg_t *src, htsmsg_t *dst)
+{
+ htsmsg_field_t *f;
+ htsmsg_t *sub;
+
+ TAILQ_FOREACH(f, &src->hm_fields, hmf_link) {
+
+ switch(f->hmf_type) {
+
+ case HMF_MAP:
+ case HMF_LIST:
+ sub = f->hmf_type == HMF_LIST ?
+ htsmsg_create_list() : htsmsg_create_map();
+ htsmsg_copy_i(&f->hmf_msg, sub);
+ htsmsg_add_msg(dst, f->hmf_name, sub);
+ break;
+
+ case HMF_STR:
+ htsmsg_add_str(dst, f->hmf_name, f->hmf_str);
+ break;
+
+ case HMF_S64:
+ htsmsg_add_s64(dst, f->hmf_name, f->hmf_s64);
+ break;
+
+ case HMF_BIN:
+ htsmsg_add_bin(dst, f->hmf_name, f->hmf_bin, f->hmf_binsize);
+ break;
+ }
+ }
+}
+
+htsmsg_t *
+htsmsg_copy(htsmsg_t *src)
+{
+ htsmsg_t *dst = src->hm_islist ? htsmsg_create_list() : htsmsg_create_map();
+ htsmsg_copy_i(src, dst);
+ return dst;
+}
diff --git a/lib/libhts/htsmsg.h b/lib/libhts/htsmsg.h
new file mode 100644
index 0000000000..a39883cf0e
--- /dev/null
+++ b/lib/libhts/htsmsg.h
@@ -0,0 +1,263 @@
+/*
+ * Functions for manipulating HTS messages
+ * Copyright (C) 2007 Andreas Öman
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef HTSMSG_H_
+#define HTSMSG_H_
+
+#include <inttypes.h>
+#include "htsq.h"
+
+#define HTSMSG_ERR_FIELD_NOT_FOUND -1
+#define HTSMSG_ERR_CONVERSION_IMPOSSIBLE -2
+
+TAILQ_HEAD(htsmsg_field_queue, htsmsg_field);
+
+typedef struct htsmsg {
+ /**
+ * fields
+ */
+ struct htsmsg_field_queue hm_fields;
+
+ /**
+ * Set if this message is a list, otherwise it is a map.
+ */
+ int hm_islist;
+
+ /**
+ * Data to be free'd when the message is destroyed
+ */
+ const void *hm_data;
+} htsmsg_t;
+
+
+#define HMF_MAP 1
+#define HMF_S64 2
+#define HMF_STR 3
+#define HMF_BIN 4
+#define HMF_LIST 5
+
+typedef struct htsmsg_field {
+ TAILQ_ENTRY(htsmsg_field) hmf_link;
+ const char *hmf_name;
+ uint8_t hmf_type;
+ uint8_t hmf_flags;
+
+#define HMF_ALLOCED 0x1
+#define HMF_NAME_ALLOCED 0x2
+
+ union {
+ int64_t s64;
+ const char *str;
+ struct {
+ const char *data;
+ size_t len;
+ } bin;
+ htsmsg_t msg;
+ } u;
+} htsmsg_field_t;
+
+#define hmf_s64 u.s64
+#define hmf_msg u.msg
+#define hmf_str u.str
+#define hmf_bin u.bin.data
+#define hmf_binsize u.bin.len
+
+#define htsmsg_get_map_by_field(f) \
+ ((f)->hmf_type == HMF_MAP ? &(f)->hmf_msg : NULL)
+
+#define HTSMSG_FOREACH(f, msg) TAILQ_FOREACH(f, &(msg)->hm_fields, hmf_link)
+
+/**
+ * Create a new map
+ */
+htsmsg_t *htsmsg_create_map(void);
+
+/**
+ * Create a new list
+ */
+htsmsg_t *htsmsg_create_list(void);
+
+/**
+ * Destroys a message (map or list)
+ */
+void htsmsg_destroy(htsmsg_t *msg);
+
+/**
+ * Add an integer field where source is unsigned 32 bit.
+ */
+void htsmsg_add_u32(htsmsg_t *msg, const char *name, uint32_t u32);
+
+/**
+ * Add an integer field where source is signed 32 bit.
+ */
+void htsmsg_add_s32(htsmsg_t *msg, const char *name, int32_t s32);
+
+/**
+ * Add an integer field where source is signed 64 bit.
+ */
+void htsmsg_add_s64(htsmsg_t *msg, const char *name, int64_t s64);
+
+/**
+ * Add a string field.
+ */
+void htsmsg_add_str(htsmsg_t *msg, const char *name, const char *str);
+
+/**
+ * Add an field where source is a list or map message.
+ */
+void htsmsg_add_msg(htsmsg_t *msg, const char *name, htsmsg_t *sub);
+
+/**
+ * Add an field where source is a list or map message.
+ *
+ * This function will not strdup() \p name but relies on the caller
+ * to keep the string allocated for as long as the message is valid.
+ */
+void htsmsg_add_msg_extname(htsmsg_t *msg, const char *name, htsmsg_t *sub);
+
+/**
+ * Add an binary field. The data is copied to a malloced storage
+ */
+void htsmsg_add_bin(htsmsg_t *msg, const char *name, const void *bin,
+ size_t len);
+
+/**
+ * Add an binary field. The data is not copied, instead the caller
+ * is responsible for keeping the data valid for as long as the message
+ * is around.
+ */
+void htsmsg_add_binptr(htsmsg_t *msg, const char *name, const void *bin,
+ size_t len);
+
+/**
+ * Get an integer as an unsigned 32 bit integer.
+ *
+ * @return HTSMSG_ERR_FIELD_NOT_FOUND - Field does not exist
+ * HTSMSG_ERR_CONVERSION_IMPOSSIBLE - Field is not an integer or
+ * out of range for the requested storage.
+ */
+int htsmsg_get_u32(htsmsg_t *msg, const char *name, uint32_t *u32p);
+
+/**
+ * Get an integer as an signed 32 bit integer.
+ *
+ * @return HTSMSG_ERR_FIELD_NOT_FOUND - Field does not exist
+ * HTSMSG_ERR_CONVERSION_IMPOSSIBLE - Field is not an integer or
+ * out of range for the requested storage.
+ */
+int htsmsg_get_s32(htsmsg_t *msg, const char *name, int32_t *s32p);
+
+/**
+ * Get an integer as an signed 64 bit integer.
+ *
+ * @return HTSMSG_ERR_FIELD_NOT_FOUND - Field does not exist
+ * HTSMSG_ERR_CONVERSION_IMPOSSIBLE - Field is not an integer or
+ * out of range for the requested storage.
+ */
+int htsmsg_get_s64(htsmsg_t *msg, const char *name, int64_t *s64p);
+
+/**
+ * Get pointer to a binary field. No copying of data is performed.
+ *
+ * @param binp Pointer to a void * that will be filled in with a pointer
+ * to the data
+ * @param lenp Pointer to a size_t that will be filled with the size of
+ * the data
+ *
+ * @return HTSMSG_ERR_FIELD_NOT_FOUND - Field does not exist
+ * HTSMSG_ERR_CONVERSION_IMPOSSIBLE - Field is not a binary blob.
+ */
+int htsmsg_get_bin(htsmsg_t *msg, const char *name, const void **binp,
+ size_t *lenp);
+
+/**
+ * Get a field of type 'list'. No copying is done.
+ *
+ * @return NULL if the field can not be found or not of list type.
+ * Otherwise a htsmsg is returned.
+ */
+htsmsg_t *htsmsg_get_list(htsmsg_t *msg, const char *name);
+
+/**
+ * Get a field of type 'string'. No copying is done.
+ *
+ * @return NULL if the field can not be found or not of string type.
+ * Otherwise a pointer to the data is returned.
+ */
+const char *htsmsg_get_str(htsmsg_t *msg, const char *name);
+
+/**
+ * Get a field of type 'map'. No copying is done.
+ *
+ * @return NULL if the field can not be found or not of map type.
+ * Otherwise a htsmsg is returned.
+ */
+htsmsg_t *htsmsg_get_map(htsmsg_t *msg, const char *name);
+
+/**
+ * Traverse a hierarchy of htsmsg's to find a specific child.
+ */
+htsmsg_t *htsmsg_get_map_multi(htsmsg_t *msg, ...);
+
+/**
+ * Given the field \p f, return a string if it is of type string, otherwise
+ * return NULL
+ */
+const char *htsmsg_field_get_string(htsmsg_field_t *f);
+
+/**
+ * Return the field \p name as an u32.
+ *
+ * @return An unsigned 32 bit integer or NULL if the field can not be found
+ * or if conversion is not possible.
+ */
+int htsmsg_get_u32_or_default(htsmsg_t *msg, const char *name, uint32_t def);
+
+/**
+ * Remove the given field called \p name from the message \p msg.
+ */
+int htsmsg_delete_field(htsmsg_t *msg, const char *name);
+
+/**
+ * Detach will remove the given field (and only if it is a list or map)
+ * from the message and make it a 'standalone message'. This means
+ * the the contents of the sub message will stay valid if the parent is
+ * destroyed. The caller is responsible for freeing this new message.
+ */
+htsmsg_t *htsmsg_detach_submsg(htsmsg_field_t *f);
+
+/**
+ * Print a message to stdout.
+ */
+void htsmsg_print(htsmsg_t *msg);
+
+/**
+ * Create a new field. Primarily intended for htsmsg internal functions.
+ */
+htsmsg_field_t *htsmsg_field_add(htsmsg_t *msg, const char *name,
+ int type, int flags);
+
+/**
+ * Clone a message.
+ */
+htsmsg_t *htsmsg_copy(htsmsg_t *src);
+
+#define HTSMSG_FOREACH(f, msg) TAILQ_FOREACH(f, &(msg)->hm_fields, hmf_link)
+
+#endif /* HTSMSG_H_ */
diff --git a/lib/libhts/htsmsg_binary.c b/lib/libhts/htsmsg_binary.c
new file mode 100644
index 0000000000..a5539765b4
--- /dev/null
+++ b/lib/libhts/htsmsg_binary.c
@@ -0,0 +1,283 @@
+/*
+ * Functions converting HTSMSGs to/from a simple binary format
+ * Copyright (C) 2007 Andreas Öman
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <assert.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "htsmsg_binary.h"
+
+/*
+ *
+ */
+static int
+htsmsg_binary_des0(htsmsg_t *msg, const uint8_t *buf, size_t len)
+{
+ unsigned type, namelen, datalen;
+ htsmsg_field_t *f;
+ htsmsg_t *sub;
+ char *n;
+ uint64_t u64;
+ int i;
+
+ while(len > 5) {
+
+ type = buf[0];
+ namelen = buf[1];
+ datalen = (buf[2] << 24) |
+ (buf[3] << 16) |
+ (buf[4] << 8 ) |
+ (buf[5] );
+
+ buf += 6;
+ len -= 6;
+
+ if(len < namelen + datalen)
+ return -1;
+
+ f = malloc(sizeof(htsmsg_field_t));
+ f->hmf_type = type;
+
+ if(namelen > 0) {
+ n = malloc(namelen + 1);
+ memcpy(n, buf, namelen);
+ n[namelen] = 0;
+
+ buf += namelen;
+ len -= namelen;
+ f->hmf_flags = HMF_NAME_ALLOCED;
+
+ } else {
+ n = NULL;
+ f->hmf_flags = 0;
+ }
+
+ f->hmf_name = n;
+
+ switch(type) {
+ case HMF_STR:
+ f->hmf_str = n = malloc(datalen + 1);
+ memcpy(n, buf, datalen);
+ n[datalen] = 0;
+ f->hmf_flags |= HMF_ALLOCED;
+ break;
+
+ case HMF_BIN:
+ f->hmf_bin = (const void *)buf;
+ f->hmf_binsize = datalen;
+ break;
+
+ case HMF_S64:
+ u64 = 0;
+ for(i = datalen - 1; i >= 0; i--)
+ u64 = (u64 << 8) | buf[i];
+ f->hmf_s64 = u64;
+ break;
+
+ case HMF_MAP:
+ case HMF_LIST:
+ sub = &f->hmf_msg;
+ TAILQ_INIT(&sub->hm_fields);
+ sub->hm_data = NULL;
+ if(htsmsg_binary_des0(sub, buf, datalen) < 0)
+ return -1;
+ break;
+
+ default:
+ free(n);
+ free(f);
+ return -1;
+ }
+
+ TAILQ_INSERT_TAIL(&msg->hm_fields, f, hmf_link);
+ buf += datalen;
+ len -= datalen;
+ }
+ return 0;
+}
+
+
+
+/*
+ *
+ */
+htsmsg_t *
+htsmsg_binary_deserialize(const void *data, size_t len, const void *buf)
+{
+ htsmsg_t *msg = htsmsg_create_map();
+ msg->hm_data = buf;
+
+ if(htsmsg_binary_des0(msg, data, len) < 0) {
+ htsmsg_destroy(msg);
+ return NULL;
+ }
+ return msg;
+}
+
+
+
+/*
+ *
+ */
+static size_t
+htsmsg_binary_count(htsmsg_t *msg)
+{
+ htsmsg_field_t *f;
+ size_t len = 0;
+ uint64_t u64;
+
+ TAILQ_FOREACH(f, &msg->hm_fields, hmf_link) {
+
+ len += 6;
+ len += f->hmf_name ? strlen(f->hmf_name) : 0;
+
+ switch(f->hmf_type) {
+ case HMF_MAP:
+ case HMF_LIST:
+ len += htsmsg_binary_count(&f->hmf_msg);
+ break;
+
+ case HMF_STR:
+ len += strlen(f->hmf_str);
+ break;
+
+ case HMF_BIN:
+ len += f->hmf_binsize;
+ break;
+
+ case HMF_S64:
+ u64 = f->hmf_s64;
+ while(u64 != 0) {
+ len++;
+ u64 = u64 >> 8;
+ }
+ break;
+ }
+ }
+ return len;
+}
+
+
+/*
+ *
+ */
+static void
+htsmsg_binary_write(htsmsg_t *msg, uint8_t *ptr)
+{
+ htsmsg_field_t *f;
+ uint64_t u64;
+ int l, i, namelen;
+
+ TAILQ_FOREACH(f, &msg->hm_fields, hmf_link) {
+ namelen = f->hmf_name ? strlen(f->hmf_name) : 0;
+ *ptr++ = f->hmf_type;
+ *ptr++ = namelen;
+
+ switch(f->hmf_type) {
+ case HMF_MAP:
+ case HMF_LIST:
+ l = htsmsg_binary_count(&f->hmf_msg);
+ break;
+
+ case HMF_STR:
+ l = strlen(f->hmf_str);
+ break;
+
+ case HMF_BIN:
+ l = f->hmf_binsize;
+ break;
+
+ case HMF_S64:
+ u64 = f->hmf_s64;
+ l = 0;
+ while(u64 != 0) {
+ l++;
+ u64 = u64 >> 8;
+ }
+ break;
+ default:
+ abort();
+ }
+
+
+ *ptr++ = l >> 24;
+ *ptr++ = l >> 16;
+ *ptr++ = l >> 8;
+ *ptr++ = l;
+
+ if(namelen > 0) {
+ memcpy(ptr, f->hmf_name, namelen);
+ ptr += namelen;
+ }
+
+ switch(f->hmf_type) {
+ case HMF_MAP:
+ case HMF_LIST:
+ htsmsg_binary_write(&f->hmf_msg, ptr);
+ break;
+
+ case HMF_STR:
+ memcpy(ptr, f->hmf_str, l);
+ break;
+
+ case HMF_BIN:
+ memcpy(ptr, f->hmf_bin, l);
+ break;
+
+ case HMF_S64:
+ u64 = f->hmf_s64;
+ for(i = 0; i < l; i++) {
+ ptr[i] = (uint8_t)(u64 & 0xFF);
+ u64 = u64 >> 8;
+ }
+ break;
+ }
+ ptr += l;
+ }
+}
+
+
+/*
+ *
+ */
+int
+htsmsg_binary_serialize(htsmsg_t *msg, void **datap, size_t *lenp, int maxlen)
+{
+ size_t len;
+ uint8_t *data;
+
+ len = htsmsg_binary_count(msg);
+ if(len + 4 > (size_t)maxlen)
+ return -1;
+
+ data = malloc(len + 4);
+
+ data[0] = len >> 24;
+ data[1] = len >> 16;
+ data[2] = len >> 8;
+ data[3] = len;
+
+ htsmsg_binary_write(msg, data + 4);
+ *datap = data;
+ *lenp = len + 4;
+ return 0;
+}
diff --git a/lib/libhts/htsmsg_binary.h b/lib/libhts/htsmsg_binary.h
new file mode 100644
index 0000000000..02b41cac73
--- /dev/null
+++ b/lib/libhts/htsmsg_binary.h
@@ -0,0 +1,34 @@
+/*
+ * Functions converting HTSMSGs to/from a simple binary format
+ * Copyright (C) 2007 Andreas Öman
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef HTSMSG_BINARY_H_
+#define HTSMSG_BINARY_H_
+
+#include "htsmsg.h"
+
+/**
+ * htsmsg_binary_deserialize
+ */
+htsmsg_t *htsmsg_binary_deserialize(const void *data, size_t len,
+ const void *buf);
+
+int htsmsg_binary_serialize(htsmsg_t *msg, void **datap, size_t *lenp,
+ int maxlen);
+
+#endif /* HTSMSG_BINARY_H_ */
diff --git a/lib/libhts/htsq.h b/lib/libhts/htsq.h
new file mode 100644
index 0000000000..5d9244c225
--- /dev/null
+++ b/lib/libhts/htsq.h
@@ -0,0 +1,146 @@
+/*
+ * sys/queue.h wrappers and helpers
+ */
+
+#ifndef HTSQ_H
+#define HTSQ_H
+
+#ifdef _MSC_VER
+#undef SLIST_ENTRY
+#include "Win32/include/sys/queue.h"
+#else
+#include <sys/queue.h>
+#endif
+
+/*
+ * Complete missing LIST-ops
+ */
+
+#ifndef LIST_FOREACH
+#define LIST_FOREACH(var, head, field) \
+ for ((var) = ((head)->lh_first); \
+ (var); \
+ (var) = ((var)->field.le_next))
+#endif
+
+#ifndef LIST_EMPTY
+#define LIST_EMPTY(head) ((head)->lh_first == NULL)
+#endif
+
+#ifndef LIST_FIRST
+#define LIST_FIRST(head) ((head)->lh_first)
+#endif
+
+#ifndef LIST_NEXT
+#define LIST_NEXT(elm, field) ((elm)->field.le_next)
+#endif
+
+#ifndef LIST_INSERT_BEFORE
+#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.le_prev = (listelm)->field.le_prev; \
+ (elm)->field.le_next = (listelm); \
+ *(listelm)->field.le_prev = (elm); \
+ (listelm)->field.le_prev = &(elm)->field.le_next; \
+} while (/*CONSTCOND*/0)
+#endif
+
+/*
+ * Complete missing TAILQ-ops
+ */
+
+#ifndef TAILQ_INSERT_BEFORE
+#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
+ (elm)->field.tqe_next = (listelm); \
+ *(listelm)->field.tqe_prev = (elm); \
+ (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
+} while (0)
+#endif
+
+#ifndef TAILQ_FOREACH
+#define TAILQ_FOREACH(var, head, field) \
+ for ((var) = ((head)->tqh_first); (var); (var) = ((var)->field.tqe_next))
+#endif
+
+#ifndef TAILQ_FIRST
+#define TAILQ_FIRST(head) ((head)->tqh_first)
+#endif
+
+#ifndef TAILQ_NEXT
+#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+#endif
+
+#ifndef TAILQ_LAST
+#define TAILQ_LAST(head, headname) \
+ (*(((struct headname *)((head)->tqh_last))->tqh_last))
+#endif
+
+#ifndef TAILQ_PREV
+#define TAILQ_PREV(elm, headname, field) \
+ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+#endif
+
+#ifndef TAILQ_FOREACH_REVERSE
+#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
+ for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \
+ (var); \
+ (var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last)))
+#endif
+
+/*
+ * Some extra functions for LIST manipulation
+ */
+
+#define LIST_MOVE(newhead, oldhead, field) do { \
+ if((oldhead)->lh_first) { \
+ (oldhead)->lh_first->field.le_prev = &(newhead)->lh_first; \
+ } \
+ (newhead)->lh_first = (oldhead)->lh_first; \
+} while (0)
+
+#define LIST_INSERT_SORTED(head, elm, field, cmpfunc) do { \
+ if(LIST_EMPTY(head)) { \
+ LIST_INSERT_HEAD(head, elm, field); \
+ } else { \
+ typeof(elm) _tmp; \
+ LIST_FOREACH(_tmp,head,field) { \
+ if(cmpfunc(elm,_tmp) <= 0) { \
+ LIST_INSERT_BEFORE(_tmp,elm,field); \
+ break; \
+ } \
+ if(!LIST_NEXT(_tmp,field)) { \
+ LIST_INSERT_AFTER(_tmp,elm,field); \
+ break; \
+ } \
+ } \
+ } \
+} while(0)
+
+#define TAILQ_INSERT_SORTED(head, elm, field, cmpfunc) do { \
+ if(TAILQ_FIRST(head) == NULL) { \
+ TAILQ_INSERT_HEAD(head, elm, field); \
+ } else { \
+ typeof(elm) _tmp; \
+ TAILQ_FOREACH(_tmp,head,field) { \
+ if(cmpfunc(elm,_tmp) <= 0) { \
+ TAILQ_INSERT_BEFORE(_tmp,elm,field); \
+ break; \
+ } \
+ if(!TAILQ_NEXT(_tmp,field)) { \
+ TAILQ_INSERT_AFTER(head,_tmp,elm,field); \
+ break; \
+ } \
+ } \
+ } \
+} while(0)
+
+#define TAILQ_MOVE(newhead, oldhead, field) do { \
+ if(TAILQ_FIRST(oldhead)) { \
+ TAILQ_FIRST(oldhead)->field.tqe_prev = &(newhead)->tqh_first; \
+ } \
+ (newhead)->tqh_first = (oldhead)->tqh_first; \
+ (newhead)->tqh_last = (oldhead)->tqh_last; \
+} while (/*CONSTCOND*/0)
+
+
+#endif /* HTSQ_H */
diff --git a/lib/libhts/htsstr.c b/lib/libhts/htsstr.c
new file mode 100644
index 0000000000..c771b3b233
--- /dev/null
+++ b/lib/libhts/htsstr.c
@@ -0,0 +1,193 @@
+/*
+ * String helper functions
+ * Copyright (C) 2008 Andreas Öman
+ * Copyright (C) 2008 Mattias Wadman
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef __APPLE__
+#include "OSXGNUReplacements.h"
+#elif defined(_MSC_VER)
+#include "msvc.h"
+#endif
+#include "htsstr.h"
+
+
+static void htsstr_argsplit_add(char ***argv, int *argc, char *s);
+static int htsstr_format0(const char *str, char *out, char **map);
+
+
+char *
+htsstr_unescape(char *str) {
+ char *s;
+
+ for(s = str; *s; s++) {
+ if(*s != '\\')
+ continue;
+
+ if(*(s + 1) == 'b')
+ *s = '\b';
+ else if(*(s + 1) == 'f')
+ *s = '\f';
+ else if(*(s + 1) == 'n')
+ *s = '\n';
+ else if(*(s + 1) == 'r')
+ *s = '\r';
+ else if(*(s + 1) == 't')
+ *s = '\t';
+ else
+ *s = *(s + 1);
+
+ if(*(s + 1)) {
+ /* shift string left, copies terminator too */
+ memmove(s + 1, s + 2, strlen(s + 2) + 1);
+ }
+ }
+
+ return str;
+}
+
+static void
+htsstr_argsplit_add(char ***argv, int *argc, char *s)
+{
+ *argv = realloc(*argv, sizeof((*argv)[0]) * (*argc + 1));
+ (*argv)[(*argc)++] = s;
+}
+
+char **
+htsstr_argsplit(const char *str) {
+ int quote = 0;
+ int inarg = 0;
+ const char *start = NULL;
+ const char *stop = NULL;
+ const char *s;
+ char **argv = NULL;
+ int argc = 0;
+
+ for(s = str; *s; s++) {
+ if(start && stop) {
+ htsstr_argsplit_add(&argv, &argc,
+ htsstr_unescape(strndup(start, stop - start)));
+ start = stop = NULL;
+ }
+
+ if(inarg) {
+ switch(*s) {
+ case '\\':
+ s++;
+ break;
+ case '"':
+ if(quote) {
+ inarg = 0;
+ quote = 0;
+ stop = s;
+ }
+ break;
+ case ' ':
+ if(quote)
+ break;
+ inarg = 0;
+ stop = s;
+ break;
+ default:
+ break;
+ }
+ } else {
+ switch(*s) {
+ case ' ':
+ break;
+ case '"':
+ quote = 1;
+ s++;
+ /* fallthru */
+ default:
+ inarg = 1;
+ start = s;
+ stop = NULL;
+ break;
+ }
+ }
+ }
+
+ if(start) {
+ if(!stop)
+ stop = str + strlen(str);
+ htsstr_argsplit_add(&argv, &argc,
+ htsstr_unescape(strndup(start, stop - start)));
+ }
+
+ htsstr_argsplit_add(&argv, &argc, NULL);
+
+ return argv;
+}
+
+void
+htsstr_argsplit_free(char **argv) {
+ int i;
+
+ for(i = 0; argv[i]; i++)
+ free(argv[i]);
+
+ free(argv);
+}
+
+static int
+htsstr_format0(const char *str, char *out, char **map) {
+ const char *s = str;
+ char *f;
+ int n = 0;
+
+ while(*s) {
+ switch(*s) {
+ case '%':
+ f = map[(unsigned char)*(s + 1)];
+ if(*(s + 1) != '%' && f) {
+ s += 2; /* skip %f * */
+ if(out)
+ strcpy(&out[n], f);
+ n += strlen(f);
+ break;
+ }
+ /* fallthru */
+ default:
+ if(out)
+ out[n] = *s;
+ s++;
+ n++;
+ break;
+ }
+ }
+
+ if(out)
+ out[n] = '\0';
+
+ return n + 1; /* + \0 */
+}
+
+char *
+htsstr_format(const char *str, char **map)
+{
+ char *s;
+
+ s = malloc(htsstr_format0(str, NULL, map));
+ htsstr_format0(str, s, map);
+
+ return s;
+}
+
diff --git a/lib/libhts/htsstr.h b/lib/libhts/htsstr.h
new file mode 100644
index 0000000000..d2f0294a9f
--- /dev/null
+++ b/lib/libhts/htsstr.h
@@ -0,0 +1,33 @@
+/*
+ * String helper functions
+ * Copyright (C) 2008 Andreas Öman
+ * Copyright (C) 2008 Mattias Wadman
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef HTSSTR_H__
+#define HTSSTR_H__
+
+char *htsstr_unescape(char *str);
+
+char **htsstr_argsplit(const char *str);
+
+void htsstr_argsplit_free(char **argv);
+
+char *htsstr_format(const char *str, char **map);
+
+#endif /* HTSSTR_H__ */
diff --git a/lib/libhts/net.h b/lib/libhts/net.h
new file mode 100644
index 0000000000..f817599abb
--- /dev/null
+++ b/lib/libhts/net.h
@@ -0,0 +1,51 @@
+/*
+ * Networking
+ * Copyright (C) 2007-2008 Andreas Öman
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef NET_H__
+#define NET_H__
+
+#include <sys/types.h>
+#include <stdint.h>
+#include "htsbuf.h"
+
+#ifdef _MSC_VER
+typedef SOCKET socket_t;
+#else
+typedef int socket_t;
+#endif
+
+socket_t htsp_tcp_connect(const char *hostname, int port, char *errbuf,
+ size_t errbufsize, int timeout);
+
+int htsp_tcp_write_queue(socket_t fd, htsbuf_queue_t *q);
+
+int htsp_tcp_read_line(socket_t fd, char *buf, const size_t bufsize,
+ htsbuf_queue_t *spill);
+
+int htsp_tcp_read_data(socket_t fd, char *buf, const size_t bufsize,
+ htsbuf_queue_t *spill);
+
+int htsp_tcp_read(socket_t fd, void *buf, size_t len);
+
+int htsp_tcp_read_timeout(socket_t fd, void *buf, size_t len, int timeout);
+
+void htsp_tcp_close(socket_t fd);
+
+
+#endif /* NET_H__ */
diff --git a/lib/libhts/net_posix.c b/lib/libhts/net_posix.c
new file mode 100644
index 0000000000..cfa22f865e
--- /dev/null
+++ b/lib/libhts/net_posix.c
@@ -0,0 +1,342 @@
+/*
+ * Networking under POSIX
+ * Copyright (C) 2007-2008 Andreas Öman
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <netdb.h>
+#ifdef __APPLE__
+/* Needed on Mac OS/X */
+#ifndef SOL_TCP
+#define SOL_TCP IPPROTO_TCP
+#endif
+#include "OSXGNUReplacements.h"
+#else
+#include <sys/epoll.h>
+#endif
+#include <poll.h>
+#include <assert.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+
+#include "net.h"
+
+
+/**
+ *
+ */
+socket_t
+htsp_tcp_connect_addr(struct addrinfo* addr, char *errbuf, size_t errbufsize,
+ int timeout)
+{
+ socket_t fd;
+ int r, err, val;
+ socklen_t errlen = sizeof(int);
+
+ fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
+ if(fd == -1) {
+ snprintf(errbuf, errbufsize, "Unable to create socket: %s",
+ strerror(errno));
+ return -1;
+ }
+
+ /**
+ * Switch to nonblocking
+ */
+ fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
+
+ r = connect(fd, addr->ai_addr, addr->ai_addrlen);
+
+ if(r == -1) {
+ if(errno == EINPROGRESS) {
+ struct pollfd pfd;
+
+ pfd.fd = fd;
+ pfd.events = POLLOUT;
+ pfd.revents = 0;
+
+ r = poll(&pfd, 1, timeout);
+ if(r == 0) {
+ /* Timeout */
+ snprintf(errbuf, errbufsize, "Connection attempt timed out");
+ close(fd);
+ return -1;
+ }
+
+ if(r == -1) {
+ snprintf(errbuf, errbufsize, "poll() error: %s", strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen);
+ } else {
+ err = errno;
+ }
+ } else {
+ err = 0;
+ }
+
+ if(err != 0) {
+ snprintf(errbuf, errbufsize, "%s", strerror(err));
+ close(fd);
+ return -1;
+ }
+
+ fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NONBLOCK);
+
+ val = 1;
+ setsockopt(fd, SOL_TCP, TCP_NODELAY, &val, sizeof(val));
+
+ return fd;
+}
+
+
+socket_t
+htsp_tcp_connect(const char *hostname, int port, char *errbuf, size_t errbufsize,
+ int timeout)
+{
+ struct addrinfo hints;
+ struct addrinfo *result, *addr;
+ char service[33];
+ int res;
+ socket_t fd = -1;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ sprintf(service, "%d", port);
+
+ res = getaddrinfo(hostname, service, &hints, &result);
+ if(res) {
+ switch(res) {
+ case EAI_NONAME:
+ snprintf(errbuf, errbufsize, "The specified host is unknown");
+ break;
+
+ case EAI_FAIL:
+ snprintf(errbuf, errbufsize, "A nonrecoverable failure in name resolution occurred");
+ break;
+
+ case EAI_MEMORY:
+ snprintf(errbuf, errbufsize, "A memory allocation failure occurred");
+ break;
+
+ case EAI_AGAIN:
+ snprintf(errbuf, errbufsize, "A temporary error occurred on an authoritative name server");
+ break;
+
+ default:
+ snprintf(errbuf, errbufsize, "Unknown error %d", res);
+ break;
+ }
+ return -1;
+ }
+
+ for(addr = result; addr; addr = addr->ai_next) {
+ fd = htsp_tcp_connect_addr(addr, errbuf, errbufsize, timeout);
+ if(fd != -1)
+ break;
+ }
+
+ freeaddrinfo(result);
+ return fd;
+}
+
+
+/**
+ *
+ */
+int
+htsp_tcp_write_queue(socket_t fd, htsbuf_queue_t *q)
+{
+ htsbuf_data_t *hd;
+ int l, r;
+
+ while((hd = TAILQ_FIRST(&q->hq_q)) != NULL) {
+ TAILQ_REMOVE(&q->hq_q, hd, hd_link);
+
+ l = hd->hd_data_len - hd->hd_data_off;
+ r = write(fd, hd->hd_data + hd->hd_data_off, l);
+ free(hd->hd_data);
+ free(hd);
+ }
+ q->hq_size = 0;
+ return 0;
+}
+
+
+/**
+ *
+ */
+static int
+tcp_fill_htsbuf_from_fd(socket_t fd, htsbuf_queue_t *hq)
+{
+ htsbuf_data_t *hd = TAILQ_LAST(&hq->hq_q, htsbuf_data_queue);
+ int c;
+
+ if(hd != NULL) {
+ /* Fill out any previous buffer */
+ c = hd->hd_data_size - hd->hd_data_len;
+
+ if(c > 0) {
+
+ c = read(fd, hd->hd_data + hd->hd_data_len, c);
+ if(c < 1)
+ return -1;
+
+ hd->hd_data_len += c;
+ hq->hq_size += c;
+ return 0;
+ }
+ }
+
+ hd = malloc(sizeof(htsbuf_data_t));
+
+ hd->hd_data_size = 1000;
+ hd->hd_data = malloc(hd->hd_data_size);
+
+ c = read(fd, hd->hd_data, hd->hd_data_size);
+ if(c < 1) {
+ free(hd->hd_data);
+ free(hd);
+ return -1;
+ }
+ hd->hd_data_len = c;
+ hd->hd_data_off = 0;
+ TAILQ_INSERT_TAIL(&hq->hq_q, hd, hd_link);
+ hq->hq_size += c;
+ return 0;
+}
+
+
+/**
+ *
+ */
+int
+htsp_tcp_read_line(socket_t fd, char *buf, const size_t bufsize, htsbuf_queue_t *spill)
+{
+ int len;
+
+ while(1) {
+ len = htsbuf_find(spill, 0xa);
+
+ if(len == -1) {
+ if(tcp_fill_htsbuf_from_fd(fd, spill) < 0)
+ return -1;
+ continue;
+ }
+
+ if(len >= (int)bufsize - 1)
+ return -1;
+
+ htsbuf_read(spill, buf, len);
+ buf[len] = 0;
+ while(len > 0 && buf[len - 1] < 32)
+ buf[--len] = 0;
+ htsbuf_drop(spill, 1); /* Drop the \n */
+ return 0;
+ }
+}
+
+
+/**
+ *
+ */
+int
+htsp_tcp_read_data(socket_t fd, char *buf, const size_t bufsize, htsbuf_queue_t *spill)
+{
+ int x, tot = htsbuf_read(spill, buf, bufsize);
+
+ if(tot == (int)bufsize)
+ return 0;
+
+ x = recv(fd, buf + tot, bufsize - tot, MSG_WAITALL);
+ if(x != (int)bufsize - tot)
+ return -1;
+
+ return 0;
+}
+
+/**
+ *
+ */
+int
+htsp_tcp_read(socket_t fd, void *buf, size_t len)
+{
+ int x = recv(fd, buf, len, MSG_WAITALL);
+
+ if(x == -1)
+ return errno;
+ if(x != (int)len)
+ return ECONNRESET;
+ return 0;
+
+}
+
+/**
+ *
+ */
+int
+htsp_tcp_read_timeout(socket_t fd, void *buf, size_t len, int timeout)
+{
+ int x, tot = 0;
+ struct pollfd fds;
+
+ assert(timeout > 0);
+
+ fds.fd = fd;
+ fds.events = POLLIN;
+ fds.revents = 0;
+
+ while(tot != (int)len) {
+
+ x = poll(&fds, 1, timeout);
+ if(x == 0)
+ return ETIMEDOUT;
+
+ x = recv(fd, buf + tot, len - tot, MSG_DONTWAIT);
+ if(x == -1) {
+ if(errno == EAGAIN)
+ continue;
+ return errno;
+ }
+
+ if(x == 0)
+ return ECONNRESET;
+
+ tot += x;
+ }
+ return 0;
+}
+
+/**
+ *
+ */
+void
+htsp_tcp_close(socket_t fd)
+{
+ close(fd);
+}
diff --git a/lib/libhts/net_winsock.c b/lib/libhts/net_winsock.c
new file mode 100644
index 0000000000..f31dac8a6b
--- /dev/null
+++ b/lib/libhts/net_winsock.c
@@ -0,0 +1,381 @@
+/*
+ * Networking under WINDOWS
+ * Copyright (C) 2007-2008 Andreas Öman
+ * Copyright (C) 2007-2008 Joakim Plate
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include <winsock2.h>
+#include <Ws2tcpip.h>
+#include "msvc.h"
+#include "net.h"
+
+#define EINPROGRESS WSAEINPROGRESS
+#define ECONNRESET WSAECONNRESET
+#define ETIMEDOUT WSAETIMEDOUT
+#define EAGAIN WSAEWOULDBLOCK
+
+#ifndef MSG_WAITALL
+#define MSG_WAITALL 0x8
+#endif
+
+static int recv_fixed (SOCKET s, char * buf, int len, int flags)
+{
+ char* org = buf;
+ int res = 1;
+
+ if((flags & MSG_WAITALL) == 0)
+ return recv(s, buf, len, flags);
+
+ flags &= ~MSG_WAITALL;
+ while(len > 0 && res > 0)
+ {
+ res = recv(s, buf, len, flags);
+ if(res < 0)
+ return res;
+
+ buf += res;
+ len -= res;
+ }
+ return buf - org;
+}
+#define recv(s, buf, len, flags) recv_fixed(s, buf, len, flags)
+
+/**
+ *
+ */
+socket_t
+htsp_tcp_connect_addr(struct addrinfo* addr, char *errbuf, size_t errbufsize,
+ int timeout)
+{
+ socket_t fd;
+ int r, err, val;
+ socklen_t errlen = sizeof(int);
+
+ fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
+ if(fd == -1) {
+ snprintf(errbuf, errbufsize, "Unable to create socket: %s",
+ strerror(WSAGetLastError()));
+ return -1;
+ }
+
+ /**
+ * Switch to nonblocking
+ */
+ val = 1;
+ ioctlsocket(fd, FIONBIO, &val);
+
+ r = connect(fd, addr->ai_addr, addr->ai_addrlen);
+
+ if(r == -1) {
+ if(WSAGetLastError() == EINPROGRESS ||
+ WSAGetLastError() == EAGAIN) {
+ fd_set fd_write, fd_except;
+ struct timeval tv;
+
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = 1000 * (timeout % 1000);
+
+ FD_ZERO(&fd_write);
+ FD_ZERO(&fd_except);
+
+ FD_SET(fd, &fd_write);
+ FD_SET(fd, &fd_except);
+
+ r = select((int)fd+1, NULL, &fd_write, &fd_except, &tv);
+
+ if(r == 0) {
+ /* Timeout */
+ snprintf(errbuf, errbufsize, "Connection attempt timed out");
+ closesocket(fd);
+ return -1;
+ }
+
+ if(r == -1) {
+ snprintf(errbuf, errbufsize, "select() error: %s", strerror(WSAGetLastError()));
+ closesocket(fd);
+ return -1;
+ }
+
+ getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen);
+ } else {
+ err = WSAGetLastError();
+ }
+ } else {
+ err = 0;
+ }
+
+ if(err != 0) {
+ snprintf(errbuf, errbufsize, "%s", strerror(err));
+ closesocket(fd);
+ return -1;
+ }
+
+ val = 0;
+ ioctlsocket(fd, FIONBIO, &val);
+
+ val = 1;
+ setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const char*)&val, sizeof(val));
+
+ return fd;
+}
+
+
+socket_t
+htsp_tcp_connect(const char *hostname, int port, char *errbuf, size_t errbufsize,
+ int timeout)
+{
+ struct addrinfo hints;
+ struct addrinfo *result, *addr;
+ char service[33];
+ int res;
+ socket_t fd = INVALID_SOCKET;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ sprintf(service, "%d", port);
+
+ res = getaddrinfo(hostname, service, &hints, &result);
+ if(res) {
+ switch(res) {
+ case EAI_NONAME:
+ snprintf(errbuf, errbufsize, "The specified host is unknown");
+ break;
+
+ case EAI_FAIL:
+ snprintf(errbuf, errbufsize, "A nonrecoverable failure in name resolution occurred");
+ break;
+
+ case EAI_MEMORY:
+ snprintf(errbuf, errbufsize, "A memory allocation failure occurred");
+ break;
+
+ case EAI_AGAIN:
+ snprintf(errbuf, errbufsize, "A temporary error occurred on an authoritative name server");
+ break;
+
+ default:
+ snprintf(errbuf, errbufsize, "Unknown error %d", res);
+ break;
+ }
+ return -1;
+ }
+
+ for(addr = result; addr; addr = addr->ai_next) {
+ fd = htsp_tcp_connect_addr(addr, errbuf, errbufsize, timeout);
+ if(fd != INVALID_SOCKET)
+ break;
+ }
+
+ freeaddrinfo(result);
+ return fd;
+}
+
+
+/**
+ *
+ */
+int
+htsp_tcp_write_queue(socket_t fd, htsbuf_queue_t *q)
+{
+ htsbuf_data_t *hd;
+ int l, r;
+
+ while((hd = TAILQ_FIRST(&q->hq_q)) != NULL) {
+ TAILQ_REMOVE(&q->hq_q, hd, hd_link);
+
+ l = hd->hd_data_len - hd->hd_data_off;
+ r = send(fd, hd->hd_data + hd->hd_data_off, l, 0);
+ free(hd->hd_data);
+ free(hd);
+ }
+ q->hq_size = 0;
+ return 0;
+}
+
+
+/**
+ *
+ */
+static int
+tcp_fill_htsbuf_from_fd(socket_t fd, htsbuf_queue_t *hq)
+{
+ htsbuf_data_t *hd = TAILQ_LAST(&hq->hq_q, htsbuf_data_queue);
+ int c;
+
+ if(hd != NULL) {
+ /* Fill out any previous buffer */
+ c = hd->hd_data_size - hd->hd_data_len;
+
+ if(c > 0) {
+
+ c = recv(fd, hd->hd_data + hd->hd_data_len, c, MSG_WAITALL);
+ if(c < 1)
+ return -1;
+
+ hd->hd_data_len += c;
+ hq->hq_size += c;
+ return 0;
+ }
+ }
+
+ hd = malloc(sizeof(htsbuf_data_t));
+
+ hd->hd_data_size = 1000;
+ hd->hd_data = malloc(hd->hd_data_size);
+
+ c = recv(fd, hd->hd_data, hd->hd_data_size, MSG_WAITALL);
+ if(c < 1) {
+ free(hd->hd_data);
+ free(hd);
+ return -1;
+ }
+ hd->hd_data_len = c;
+ hd->hd_data_off = 0;
+ TAILQ_INSERT_TAIL(&hq->hq_q, hd, hd_link);
+ hq->hq_size += c;
+ return 0;
+}
+
+
+/**
+ *
+ */
+int
+htsp_tcp_read_line(socket_t fd, char *buf, const size_t bufsize, htsbuf_queue_t *spill)
+{
+ int len;
+
+ while(1) {
+ len = htsbuf_find(spill, 0xa);
+
+ if(len == -1) {
+ if(tcp_fill_htsbuf_from_fd(fd, spill) < 0)
+ return -1;
+ continue;
+ }
+
+ if(len >= (int)bufsize - 1)
+ return -1;
+
+ htsbuf_read(spill, buf, len);
+ buf[len] = 0;
+ while(len > 0 && buf[len - 1] < 32)
+ buf[--len] = 0;
+ htsbuf_drop(spill, 1); /* Drop the \n */
+ return 0;
+ }
+}
+
+
+/**
+ *
+ */
+int
+htsp_tcp_read_data(socket_t fd, char *buf, const size_t bufsize, htsbuf_queue_t *spill)
+{
+ int x, tot = htsbuf_read(spill, buf, bufsize);
+
+ if(tot == bufsize)
+ return 0;
+
+ x = recv(fd, buf + tot, bufsize - tot, MSG_WAITALL);
+ if(x != bufsize - tot)
+ return -1;
+
+ return 0;
+}
+
+/**
+ *
+ */
+int
+htsp_tcp_read(socket_t fd, void *buf, size_t len)
+{
+ int x = recv(fd, buf, len, MSG_WAITALL);
+
+ if(x == -1)
+ return WSAGetLastError();
+ if(x != len)
+ return ECONNRESET;
+ return 0;
+
+}
+
+/**
+ *
+ */
+int
+htsp_tcp_read_timeout(socket_t fd, char *buf, size_t len, int timeout)
+{
+ int x, tot = 0, val, err;
+ fd_set fd_read;
+ struct timeval tv;
+
+ assert(timeout > 0);
+
+ while(tot != len) {
+
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = 1000 * (timeout % 1000);
+
+ FD_ZERO(&fd_read);
+ FD_SET(fd, &fd_read);
+
+ x = select((int)fd+1, &fd_read, NULL, NULL, &tv);
+
+ if(x == 0)
+ return ETIMEDOUT;
+
+ val = 1;
+ ioctlsocket(fd, FIONBIO, &val);
+
+ x = recv(fd, buf + tot, len - tot, 0);
+ err = WSAGetLastError();
+
+ val = 0;
+ ioctlsocket(fd, FIONBIO, &val);
+
+ if(x == 0)
+ return ECONNRESET;
+ else if(x == -1)
+ {
+ if(err == EAGAIN)
+ continue;
+ return err;
+ }
+
+ tot += x;
+ }
+ return 0;
+}
+
+/**
+ *
+ */
+void
+htsp_tcp_close(socket_t fd)
+{
+ closesocket(fd);
+}
diff --git a/lib/libhts/sha1.c b/lib/libhts/sha1.c
new file mode 100644
index 0000000000..0867b942e6
--- /dev/null
+++ b/lib/libhts/sha1.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2007 Michael Niedermayer <michaelni@gmx.at>
+ * based on public domain SHA-1 code by Steve Reid <steve@edmweb.com>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Modified by Joakim Plate <elupus@ecce.se> to be stand alone from libavutil
+ */
+
+#include "sha1.h"
+#include <string.h>
+
+
+static uint16_t bswap_16(uint16_t x)
+{
+ x= (x>>8) | (x<<8);
+ return x;
+}
+
+
+static uint32_t bswap_32(uint32_t x)
+{
+ x= ((x<<8)&0xFF00FF00) | ((x>>8)&0x00FF00FF);
+ x= (x>>16) | (x<<16);
+ return x;
+}
+
+static uint64_t bswap_64(uint64_t x)
+{
+ union {
+ uint64_t ll;
+ uint32_t l[2];
+ } w, r;
+ w.ll = x;
+ r.l[0] = bswap_32 (w.l[1]);
+ r.l[1] = bswap_32 (w.l[0]);
+ return r.ll;
+}
+
+// be2me ... big-endian to machine-endian
+// le2me ... little-endian to machine-endian
+
+#ifdef WORDS_BIGENDIAN
+#define be2me_16(x) (x)
+#define be2me_32(x) (x)
+#define be2me_64(x) (x)
+#define le2me_16(x) bswap_16(x)
+#define le2me_32(x) bswap_32(x)
+#define le2me_64(x) bswap_64(x)
+#else
+#define be2me_16(x) bswap_16(x)
+#define be2me_32(x) bswap_32(x)
+#define be2me_64(x) bswap_64(x)
+#define le2me_16(x) (x)
+#define le2me_32(x) (x)
+#define le2me_64(x) (x)
+#endif
+
+typedef struct HTSSHA1 {
+ uint64_t count;
+ uint8_t buffer[64];
+ uint32_t state[5];
+} HTSSHA1;
+
+const int hts_sha1_size = sizeof(HTSSHA1);
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+#define blk0(i) (block[i] = be2me_32(((const uint32_t*)buffer)[i]))
+#define blk(i) (block[i] = rol(block[i-3]^block[i-8]^block[i-14]^block[i-16],1))
+
+#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y) +blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y) +blk (i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R2(v,w,x,y,z,i) z+=( w^x ^y) +blk (i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
+#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk (i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
+#define R4(v,w,x,y,z,i) z+=( w^x ^y) +blk (i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
+
+/* Hash a single 512-bit block. This is the core of the algorithm. */
+
+static void transform(uint32_t state[5], const uint8_t buffer[64]){
+ uint32_t block[80];
+ unsigned int i, a, b, c, d, e;
+
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+ e = state[4];
+#if CONFIG_SMALL
+ for(i=0; i<80; i++){
+ int t;
+ if(i<16) t= be2me_32(((uint32_t*)buffer)[i]);
+ else t= rol(block[i-3]^block[i-8]^block[i-14]^block[i-16],1);
+ block[i]= t;
+ t+= e+rol(a,5);
+ if(i<40){
+ if(i<20) t+= ((b&(c^d))^d) +0x5A827999;
+ else t+= ( b^c ^d) +0x6ED9EBA1;
+ }else{
+ if(i<60) t+= (((b|c)&d)|(b&c))+0x8F1BBCDC;
+ else t+= ( b^c ^d) +0xCA62C1D6;
+ }
+ e= d;
+ d= c;
+ c= rol(b,30);
+ b= a;
+ a= t;
+ }
+#else
+ for(i=0; i<15; i+=5){
+ R0(a,b,c,d,e,0+i); R0(e,a,b,c,d,1+i); R0(d,e,a,b,c,2+i); R0(c,d,e,a,b,3+i); R0(b,c,d,e,a,4+i);
+ }
+ R0(a,b,c,d,e,15); R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+ for(i=20; i<40; i+=5){
+ R2(a,b,c,d,e,0+i); R2(e,a,b,c,d,1+i); R2(d,e,a,b,c,2+i); R2(c,d,e,a,b,3+i); R2(b,c,d,e,a,4+i);
+ }
+ for(; i<60; i+=5){
+ R3(a,b,c,d,e,0+i); R3(e,a,b,c,d,1+i); R3(d,e,a,b,c,2+i); R3(c,d,e,a,b,3+i); R3(b,c,d,e,a,4+i);
+ }
+ for(; i<80; i+=5){
+ R4(a,b,c,d,e,0+i); R4(e,a,b,c,d,1+i); R4(d,e,a,b,c,2+i); R4(c,d,e,a,b,3+i); R4(b,c,d,e,a,4+i);
+ }
+#endif
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+ state[4] += e;
+}
+
+void hts_sha1_init(HTSSHA1* ctx){
+ ctx->state[0] = 0x67452301;
+ ctx->state[1] = 0xEFCDAB89;
+ ctx->state[2] = 0x98BADCFE;
+ ctx->state[3] = 0x10325476;
+ ctx->state[4] = 0xC3D2E1F0;
+ ctx->count = 0;
+}
+
+void hts_sha1_update(HTSSHA1* ctx, const uint8_t* data, unsigned int len){
+ unsigned int i, j;
+
+ j = ctx->count & 63;
+ ctx->count += len;
+#if CONFIG_SMALL
+ for( i = 0; i < len; i++ ){
+ ctx->buffer[ j++ ] = data[i];
+ if( 64 == j ){
+ transform(ctx->state, ctx->buffer);
+ j = 0;
+ }
+ }
+#else
+ if ((j + len) > 63) {
+ memcpy(&ctx->buffer[j], data, (i = 64-j));
+ transform(ctx->state, ctx->buffer);
+ for ( ; i + 63 < len; i += 64) {
+ transform(ctx->state, &data[i]);
+ }
+ j=0;
+ }
+ else i = 0;
+ memcpy(&ctx->buffer[j], &data[i], len - i);
+#endif
+}
+
+void hts_sha1_final(HTSSHA1* ctx, uint8_t digest[20]){
+ int i;
+ uint64_t finalcount= be2me_64(ctx->count<<3);
+
+ hts_sha1_update(ctx, (const uint8_t*)"\200", 1);
+ while ((ctx->count & 63) != 56) {
+ hts_sha1_update(ctx, (const uint8_t*)"", 1);
+ }
+ hts_sha1_update(ctx, (uint8_t *)&finalcount, 8); /* Should cause a transform() */
+ for(i=0; i<5; i++)
+ ((uint32_t*)digest)[i]= be2me_32(ctx->state[i]);
+}
+
+#ifdef TEST
+#include <stdio.h>
+#undef printf
+
+int main(void){
+ int i, k;
+ HTSSHA1 ctx;
+ unsigned char digest[20];
+
+ for(k=0; k<3; k++){
+ av_sha1_init(&ctx);
+ if(k==0)
+ av_sha1_update(&ctx, "abc", 3);
+ else if(k==1)
+ av_sha1_update(&ctx, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56);
+ else
+ for(i=0; i<1000*1000; i++)
+ av_sha1_update(&ctx, "a", 1);
+ av_sha1_final(&ctx, digest);
+ for (i = 0; i < 20; i++)
+ printf("%02X", digest[i]);
+ putchar('\n');
+ }
+ //test vectors (from FIPS PUB 180-1)
+ printf("A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D\n"
+ "84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1\n"
+ "34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F\n");
+
+ return 0;
+}
+#endif
diff --git a/lib/libhts/sha1.h b/lib/libhts/sha1.h
new file mode 100644
index 0000000000..e4ce492699
--- /dev/null
+++ b/lib/libhts/sha1.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2007 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Modified by Joakim Plate <elupus@ecce.se> to be stand alone from libavutil
+ */
+
+#ifndef HTS_SHA1_H
+#define HTS_SHA1_H
+
+#include <stdint.h>
+
+extern const int hts_sha1_size;
+
+struct HTSSHA1;
+
+void hts_sha1_init(struct HTSSHA1* context);
+void hts_sha1_update(struct HTSSHA1* context, const uint8_t* data, unsigned int len);
+void hts_sha1_final(struct HTSSHA1* context, uint8_t digest[20]);
+
+#endif /* HTS_SHA1_H */