diff options
author | theuni <theuni-nospam-@xbmc.org> | 2011-01-24 16:05:21 -0500 |
---|---|---|
committer | theuni <theuni-nospam-@xbmc.org> | 2011-01-24 16:05:21 -0500 |
commit | c51b1189e3d5353e842991f5859ddcea0f73e426 (patch) | |
tree | ef2cb8a6184699aa614f3655dca4ce661cdc108e /lib/libhts | |
parent | be61ebdc9e897fe40c6f371111724de79ddee8d5 (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')
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=""$(ProjectDir)include"" + 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=""$(ProjectDir)include"" + 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=""$(ProjectDir)include"" + 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=""$(ProjectDir)include"" + 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 */ |