MINOR: 51d: Added dummy libraries for the 51Degrees module for testing.

These are intended for use by HAProxy developers to ensure any changes
did not affect the 51Degrees implementation. The 51Degrees module can be
enabled and used by using the source in contrib/51d. This will run
without breaking, but will not return any meaningful information.

This is ideal for testing HAProxy core code, and other modules alongside
51Degrees, but should never be used as an actual module as it does
nothing.
diff --git a/contrib/51d/cityhash/city.c b/contrib/51d/cityhash/city.c
new file mode 100644
index 0000000..b6b08bf
--- /dev/null
+++ b/contrib/51d/cityhash/city.c
@@ -0,0 +1,4 @@
+typedef struct cityhash_t {
+    // This is an empty structure to ensure a city.o is generated
+    // by the dummy library, it is never used.
+} dummyCityHash;
\ No newline at end of file
diff --git a/contrib/51d/pattern/51Degrees.c b/contrib/51d/pattern/51Degrees.c
new file mode 100644
index 0000000..c002e5c
--- /dev/null
+++ b/contrib/51d/pattern/51Degrees.c
@@ -0,0 +1,114 @@
+/* *********************************************************************
+ * This Source Code Form is copyright of 51Degrees Mobile Experts Limited.
+ * Copyright 2019 51Degrees Mobile Experts Limited, 5 Charlotte Close,
+ * Caversham, Reading, Berkshire, United Kingdom RG4 7BY
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0.
+ *
+ * If a copy of the MPL was not distributed with this file, You can obtain
+ * one at http://mozilla.org/MPL/2.0/.
+ *
+ * This Source Code Form is "Incompatible With Secondary Licenses", as
+ * defined by the Mozilla Public License, v. 2.0.
+ * *********************************************************************/
+
+/* *********************************************************************
+ * Dummy library for HAProxy. This does not function, and is designed
+ * solely for HAProxy testing purposes.
+ * *********************************************************************/
+#include "51Degrees.h"
+#include <stdlib.h>
+
+int32_t fiftyoneDegreesGetSignatureRank(fiftyoneDegreesWorkset *ws) {
+    return 0;
+}
+
+const char* fiftyoneDegreesGetPropertyName(
+	const fiftyoneDegreesDataSet *dataSet,
+	const fiftyoneDegreesProperty *property) {
+    return "dummy-property";
+}
+
+int32_t fiftyoneDegreesSetValues(
+	fiftyoneDegreesWorkset *ws,
+	int32_t requiredPropertyIndex) {
+    return 0;
+}
+
+const char* fiftyoneDegreesGetValueName(
+	const fiftyoneDegreesDataSet *dataSet,
+	const fiftyoneDegreesValue *value) {
+    return "dummy-value";
+}
+
+static fiftyoneDegreesDataSet dummyDataSet = {
+    0,
+    (fiftyoneDegreesHttpHeader*)NULL,
+    0,
+    (const fiftyoneDegreesProperty**)NULL
+};
+
+static fiftyoneDegreesWorkset dummyWorkset = {
+	&dummyDataSet,
+	0,
+	(fiftyoneDegreesHttpHeaderWorkset*)NULL,
+    EXACT,
+    0,
+    (const fiftyoneDegreesValue **)NULL
+};
+
+fiftyoneDegreesWorkset *fiftyoneDegreesWorksetPoolGet(
+	fiftyoneDegreesWorksetPool *pool) {
+    return &dummyWorkset;
+}
+
+void fiftyoneDegreesWorksetPoolRelease(
+    fiftyoneDegreesWorksetPool *pool,
+    fiftyoneDegreesWorkset *ws) {
+    return;
+}
+
+void fiftyoneDegreesMatchForHttpHeaders(fiftyoneDegreesWorkset *ws) {
+    return;
+}
+
+void fiftyoneDegreesMatch(
+	fiftyoneDegreesWorkset *ws,
+	const char* userAgent) {
+    return;
+}
+
+fiftyoneDegreesDataSetInitStatus fiftyoneDegreesInitWithPropertyArray(
+	const char *fileName,
+	fiftyoneDegreesDataSet *dataSet,
+	const char** properties,
+	int32_t count) {
+    return DATA_SET_INIT_STATUS_SUCCESS;
+}
+
+static fiftyoneDegreesWorksetPool dummyWorksetPool;
+
+fiftyoneDegreesWorksetPool *fiftyoneDegreesWorksetPoolCreate(
+	fiftyoneDegreesDataSet *dataSet,
+	fiftyoneDegreesResultsetCache *cache,
+	int32_t size) {
+    return &dummyWorksetPool;
+}
+
+void fiftyoneDegreesWorksetPoolFree(
+	const fiftyoneDegreesWorksetPool *pool) {
+    return;
+}
+
+void fiftyoneDegreesDataSetFree(const fiftyoneDegreesDataSet *dataSet) {
+    return;
+}
+
+static fiftyoneDegreesAsciiString dummyAsciiString = {0, 0};
+
+const fiftyoneDegreesAsciiString* fiftyoneDegreesGetString(
+	const fiftyoneDegreesDataSet *dataSet,
+	int32_t offset) {
+		return &dummyAsciiString;
+}
\ No newline at end of file
diff --git a/contrib/51d/pattern/51Degrees.h b/contrib/51d/pattern/51Degrees.h
new file mode 100644
index 0000000..6a646a6
--- /dev/null
+++ b/contrib/51d/pattern/51Degrees.h
@@ -0,0 +1,143 @@
+/* *********************************************************************
+ * This Source Code Form is copyright of 51Degrees Mobile Experts Limited.
+ * Copyright 2019 51Degrees Mobile Experts Limited, 5 Charlotte Close,
+ * Caversham, Reading, Berkshire, United Kingdom RG4 7BY
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0.
+ *
+ * If a copy of the MPL was not distributed with this file, You can obtain
+ * one at http://mozilla.org/MPL/2.0/.
+ *
+ * This Source Code Form is "Incompatible With Secondary Licenses", as
+ * defined by the Mozilla Public License, v. 2.0.
+ * *********************************************************************/
+
+/* *********************************************************************
+ * Dummy library for HAProxy. This does not function, and is designed
+ * solely for HAProxy testing purposes.
+ * *********************************************************************/
+#ifndef FIFTYONEDEGREES_H_INCLUDED
+#define FIFTYONEDEGREES_H_INCLUDED
+
+#ifndef FIFTYONEDEGREES_H_PATTERN_INCLUDED
+#define FIFTYONEDEGREES_H_PATTERN_INCLUDED
+#endif
+
+#include <stdint.h>
+
+typedef enum e_fiftyoneDegrees_MatchMethod {
+	NONE,
+	EXACT,
+	NUMERIC,
+	NEAREST,
+	CLOSEST
+} fiftyoneDegreesMatchMethod;
+
+typedef enum e_fiftyoneDegrees_DataSetInitStatus {
+	DATA_SET_INIT_STATUS_SUCCESS,
+	DATA_SET_INIT_STATUS_INSUFFICIENT_MEMORY,
+	DATA_SET_INIT_STATUS_CORRUPT_DATA,
+	DATA_SET_INIT_STATUS_INCORRECT_VERSION,
+	DATA_SET_INIT_STATUS_FILE_NOT_FOUND,
+	DATA_SET_INIT_STATUS_NOT_SET,
+	DATA_SET_INIT_STATUS_POINTER_OUT_OF_BOUNDS,
+	DATA_SET_INIT_STATUS_NULL_POINTER
+} fiftyoneDegreesDataSetInitStatus;
+
+typedef struct fiftyoneDegrees_ascii_string_t {
+	const int16_t length;
+	const char firstByte;
+} fiftyoneDegreesAsciiString;
+
+typedef struct fiftyoneDegrees_dataset_header_t {
+} fiftyoneDegreesDataSetHeader;
+
+typedef struct fiftyoneDegrees_workset_pool_t {
+} fiftyoneDegreesWorksetPool;
+
+typedef struct fiftyoneDegrees_property_t {
+} fiftyoneDegreesProperty;
+
+typedef struct fiftyoneDegrees_value_t {
+} fiftyoneDegreesValue;
+
+typedef struct fiftyoneDegrees_resultset_cache_t {
+} fiftyoneDegreesResultsetCache;
+
+typedef struct fiftyoneDegrees_http_header_t {
+	int32_t headerNameOffset;
+	const char *headerName;
+} fiftyoneDegreesHttpHeader;
+
+typedef struct fiftyoneDegrees_http_header_workset_t {
+	fiftyoneDegreesHttpHeader *header;
+	const char *headerValue;
+	int headerValueLength;
+} fiftyoneDegreesHttpHeaderWorkset;
+
+
+typedef struct fiftyoneDegrees_dataset_t {
+    int32_t httpHeadersCount;
+    fiftyoneDegreesHttpHeader *httpHeaders;
+    int32_t requiredPropertyCount;
+    const fiftyoneDegreesProperty **requiredProperties;
+} fiftyoneDegreesDataSet;
+
+typedef struct fiftyoneDegrees_workset_t {
+    fiftyoneDegreesDataSet *dataSet;
+	int32_t importantHeadersCount;
+	fiftyoneDegreesHttpHeaderWorkset *importantHeaders;
+    fiftyoneDegreesMatchMethod method;
+    int32_t difference;
+    const fiftyoneDegreesValue **values;
+} fiftyoneDegreesWorkset;
+
+int32_t fiftyoneDegreesGetSignatureRank(fiftyoneDegreesWorkset *ws);
+
+const char* fiftyoneDegreesGetPropertyName(
+	const fiftyoneDegreesDataSet *dataSet,
+	const fiftyoneDegreesProperty *property);
+
+int32_t fiftyoneDegreesSetValues(
+	fiftyoneDegreesWorkset *ws,
+	int32_t requiredPropertyIndex);
+
+const char* fiftyoneDegreesGetValueName(
+	const fiftyoneDegreesDataSet *dataSet,
+	const fiftyoneDegreesValue *value);
+
+fiftyoneDegreesWorkset *fiftyoneDegreesWorksetPoolGet(
+	fiftyoneDegreesWorksetPool *pool);
+
+void fiftyoneDegreesWorksetPoolRelease(
+    fiftyoneDegreesWorksetPool *pool,
+    fiftyoneDegreesWorkset *ws);
+
+void fiftyoneDegreesMatchForHttpHeaders(fiftyoneDegreesWorkset *ws);
+
+void fiftyoneDegreesMatch(
+	fiftyoneDegreesWorkset *ws,
+	const char* userAgent);
+
+fiftyoneDegreesDataSetInitStatus fiftyoneDegreesInitWithPropertyArray(
+	const char *fileName,
+	fiftyoneDegreesDataSet *dataSet,
+	const char** properties,
+	int32_t count);
+
+fiftyoneDegreesWorksetPool *fiftyoneDegreesWorksetPoolCreate(
+	fiftyoneDegreesDataSet *dataSet,
+	fiftyoneDegreesResultsetCache *cache,
+	int32_t size);
+
+void fiftyoneDegreesWorksetPoolFree(
+	const fiftyoneDegreesWorksetPool *pool);
+
+void fiftyoneDegreesDataSetFree(const fiftyoneDegreesDataSet *dataSet);
+
+const fiftyoneDegreesAsciiString* fiftyoneDegreesGetString(
+	const fiftyoneDegreesDataSet *dataSet,
+	int32_t offset);
+
+#endif
\ No newline at end of file
diff --git a/contrib/51d/threading.c b/contrib/51d/threading.c
new file mode 100644
index 0000000..e65678d
--- /dev/null
+++ b/contrib/51d/threading.c
@@ -0,0 +1,4 @@
+typedef struct fiftyoneDegrees_threading_t {
+    // This is an empty structure to ensure a threading.o is generated
+    // by the dummy library, it is never used.
+} dummyFiftyoneDegreesThreading;
\ No newline at end of file
diff --git a/contrib/51d/trie/51Degrees.c b/contrib/51d/trie/51Degrees.c
new file mode 100644
index 0000000..7453061
--- /dev/null
+++ b/contrib/51d/trie/51Degrees.c
@@ -0,0 +1,89 @@
+/* *********************************************************************
+ * This Source Code Form is copyright of 51Degrees Mobile Experts Limited.
+ * Copyright 2019 51Degrees Mobile Experts Limited, 5 Charlotte Close,
+ * Caversham, Reading, Berkshire, United Kingdom RG4 7BY
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0.
+ *
+ * If a copy of the MPL was not distributed with this file, You can obtain
+ * one at http://mozilla.org/MPL/2.0/.
+ *
+ * This Source Code Form is "Incompatible With Secondary Licenses", as
+ * defined by the Mozilla Public License, v. 2.0.
+ * *********************************************************************/
+
+/* *********************************************************************
+ * Dummy library for HAProxy. This does not function, and is designed
+ * solely for HAProxy testing purposes.
+ * *********************************************************************/
+#include "51Degrees.h"
+#include <stdlib.h>
+
+int fiftyoneDegreesGetDeviceOffset(
+	fiftyoneDegreesDataSet *dataSet,
+	const char *userAgent) {
+    return 0;
+}
+
+const char** fiftyoneDegreesGetRequiredPropertiesNames(
+	fiftyoneDegreesDataSet *dataSet) {
+    return NULL;
+}
+
+int fiftyoneDegreesGetRequiredPropertiesCount(
+	fiftyoneDegreesDataSet *dataSet) {
+    return 0;
+}
+
+int fiftyoneDegreesGetValueFromOffsets(
+	fiftyoneDegreesDataSet *dataSet,
+	fiftyoneDegreesDeviceOffsets* deviceOffsets,
+	int requiredPropertyIndex,
+	char* values,
+	int size) {
+    return 0;
+}
+
+static fiftyoneDegreesDeviceOffset dummyOffset = { 0, 0, "dummy-user-agent" };
+
+static fiftyoneDegreesDeviceOffsets dummyOffsets = { 1, &dummyOffset, NULL };
+
+fiftyoneDegreesDeviceOffsets* fiftyoneDegreesCreateDeviceOffsets(
+	fiftyoneDegreesDataSet *dataSet) {
+    return &dummyOffsets;
+}
+
+void fiftyoneDegreesFreeDeviceOffsets(
+	fiftyoneDegreesDeviceOffsets* offsets) {
+    return;
+}
+
+int fiftyoneDegreesGetHttpHeaderCount(
+	fiftyoneDegreesDataSet *dataSet) {
+    return 0;
+}
+
+int fiftyoneDegreesGetHttpHeaderNameOffset(
+	fiftyoneDegreesDataSet *dataSet,
+	int httpHeaderIndex) {
+    return 0;
+}
+
+const char* fiftyoneDegreesGetHttpHeaderNamePointer(
+	fiftyoneDegreesDataSet *dataSet,
+	int httpHeaderIndex) {
+    return "dummy-header-name";
+}
+
+fiftyoneDegreesDataSetInitStatus fiftyoneDegreesInitWithPropertyArray(
+	const char* fileName,
+	fiftyoneDegreesDataSet *dataSet,
+	const char** properties,
+	int propertyCount) {
+    return DATA_SET_INIT_STATUS_SUCCESS;
+}
+
+void fiftyoneDegreesDataSetFree(fiftyoneDegreesDataSet *dataSet) {
+    return;
+}
\ No newline at end of file
diff --git a/contrib/51d/trie/51Degrees.h b/contrib/51d/trie/51Degrees.h
new file mode 100644
index 0000000..a5f0868
--- /dev/null
+++ b/contrib/51d/trie/51Degrees.h
@@ -0,0 +1,108 @@
+/* *********************************************************************
+ * This Source Code Form is copyright of 51Degrees Mobile Experts Limited.
+ * Copyright 2019 51Degrees Mobile Experts Limited, 5 Charlotte Close,
+ * Caversham, Reading, Berkshire, United Kingdom RG4 7BY
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0.
+ *
+ * If a copy of the MPL was not distributed with this file, You can obtain
+ * one at http://mozilla.org/MPL/2.0/.
+ *
+ * This Source Code Form is "Incompatible With Secondary Licenses", as
+ * defined by the Mozilla Public License, v. 2.0.
+ * *********************************************************************/
+
+/* *********************************************************************
+ * Dummy library for HAProxy. This does not function, and is designed
+ * solely for HAProxy testing purposes.
+ * *********************************************************************/
+#ifndef FIFTYONEDEGREES_H_INCLUDED
+#define FIFTYONEDEGREES_H_INCLUDED
+
+#ifndef FIFTYONEDEGREES_H_TRIE_INCLUDED
+#define FIFTYONEDEGREES_H_TRIE_INCLUDED
+#endif
+
+#include <stdint.h>
+
+typedef enum e_fiftyoneDegrees_DataSetInitStatus {
+	DATA_SET_INIT_STATUS_SUCCESS,
+	DATA_SET_INIT_STATUS_INSUFFICIENT_MEMORY,
+	DATA_SET_INIT_STATUS_CORRUPT_DATA,
+	DATA_SET_INIT_STATUS_INCORRECT_VERSION,
+	DATA_SET_INIT_STATUS_FILE_NOT_FOUND,
+	DATA_SET_INIT_STATUS_NOT_SET,
+	DATA_SET_INIT_STATUS_POINTER_OUT_OF_BOUNDS,
+	DATA_SET_INIT_STATUS_NULL_POINTER
+} fiftyoneDegreesDataSetInitStatus;
+
+typedef struct fiftyoneDegrees_integers_t {
+	int32_t *firstElement;
+	unsigned int count;
+	int freeMemory;
+} fiftyoneDegreesIntegers;
+
+typedef struct fiftyoneDegrees_dataset_t {
+    fiftyoneDegreesIntegers uniqueHttpHeaders;
+} fiftyoneDegreesDataSet;
+
+typedef struct fiftyoneDegrees_active_dataset_t {
+
+} fiftyoneDegreesActiveDataSet;
+
+typedef struct fiftyoneDegrees_device_offset_t {
+    int httpHeaderOffset;
+    int deviceOffset;
+    char *userAgent;
+} fiftyoneDegreesDeviceOffset;
+
+typedef struct fiftyoneDegrees_device_offsets_t {
+    int size;
+	fiftyoneDegreesDeviceOffset *firstOffset;
+	fiftyoneDegreesActiveDataSet *active;
+} fiftyoneDegreesDeviceOffsets;
+
+int fiftyoneDegreesGetDeviceOffset(
+	fiftyoneDegreesDataSet *dataSet,
+	const char *userAgent);
+
+const char** fiftyoneDegreesGetRequiredPropertiesNames(
+	fiftyoneDegreesDataSet *dataSet);
+
+int fiftyoneDegreesGetRequiredPropertiesCount(
+	fiftyoneDegreesDataSet *dataSet);
+
+int fiftyoneDegreesGetValueFromOffsets(
+	fiftyoneDegreesDataSet *dataSet,
+	fiftyoneDegreesDeviceOffsets* deviceOffsets,
+	int requiredPropertyIndex,
+	char* values,
+	int size);
+
+fiftyoneDegreesDeviceOffsets* fiftyoneDegreesCreateDeviceOffsets(
+	fiftyoneDegreesDataSet *dataSet);
+
+void fiftyoneDegreesFreeDeviceOffsets(
+	fiftyoneDegreesDeviceOffsets* offsets);
+
+int fiftyoneDegreesGetHttpHeaderCount(
+	fiftyoneDegreesDataSet *dataSet);
+
+int fiftyoneDegreesGetHttpHeaderNameOffset(
+	fiftyoneDegreesDataSet *dataSet,
+	int httpHeaderIndex);
+
+const char* fiftyoneDegreesGetHttpHeaderNamePointer(
+	fiftyoneDegreesDataSet *dataSet,
+	int httpHeaderIndex);
+
+fiftyoneDegreesDataSetInitStatus fiftyoneDegreesInitWithPropertyArray(
+	const char* fileName,
+	fiftyoneDegreesDataSet *dataSet,
+	const char** properties,
+	int propertyCount);
+
+void fiftyoneDegreesDataSetFree(fiftyoneDegreesDataSet *dataSet);
+
+#endif
\ No newline at end of file