From 3e9a2a7419714c294be0590aab24f2dc040581f5 Mon Sep 17 00:00:00 2001
From: Inada Naoki <songofacandy@gmail.com>
Date: Sat, 4 May 2024 16:01:48 +0900
Subject: [PATCH] Stop using c++ (#600)

Python 3.13a6+ & C++ & Cython cause compile error on some compilers.
---
 .github/workflows/test.yml        |  2 +-
 Makefile                          |  2 +-
 msgpack/_unpacker.pyx             |  2 +-
 msgpack/pack.h                    |  2 +
 msgpack/unpack_container_header.h | 51 +++++++++++++++++++
 msgpack/unpack_template.h         | 85 ++++++++-----------------------
 setup.py                          |  6 +--
 7 files changed, 81 insertions(+), 69 deletions(-)
 create mode 100644 msgpack/unpack_container_header.h

Index: msgpack-python-0.4.6/msgpack/_unpacker.pyx
===================================================================
--- msgpack-python-0.4.6.orig/msgpack/_unpacker.pyx
+++ msgpack-python-0.4.6/msgpack/_unpacker.pyx
@@ -26,8 +26,8 @@ cdef extern from "unpack.h":
         bint has_pairs_hook # call object_hook with k-v pairs
         PyObject* list_hook
         PyObject* ext_hook
-        char *encoding
-        char *unicode_errors
+        const char *encoding
+        const char *unicode_errors
         Py_ssize_t max_str_len
         Py_ssize_t max_bin_len
         Py_ssize_t max_array_len
Index: msgpack-python-0.4.6/msgpack/pack.h
===================================================================
--- msgpack-python-0.4.6.orig/msgpack/pack.h
+++ msgpack-python-0.4.6/msgpack/pack.h
@@ -24,6 +24,8 @@
 
 #ifdef __cplusplus
 extern "C" {
+#else
+#define bool char
 #endif
 
 #ifdef _MSC_VER
Index: msgpack-python-0.4.6/msgpack/unpack_container_header.h
===================================================================
--- /dev/null
+++ msgpack-python-0.4.6/msgpack/unpack_container_header.h
@@ -0,0 +1,51 @@
+static inline int unpack_container_header(unpack_context* ctx, const char* data, Py_ssize_t len, Py_ssize_t* off)
+{
+    assert(len >= *off);
+    uint32_t size;
+    const unsigned char *const p = (unsigned char*)data + *off;
+
+#define inc_offset(inc) \
+    if (len - *off < inc) \
+        return 0; \
+    *off += inc;
+
+    switch (*p) {
+    case var_offset:
+        inc_offset(3);
+        size = _msgpack_load16(uint16_t, p + 1);
+        break;
+    case var_offset + 1:
+        inc_offset(5);
+        size = _msgpack_load32(uint32_t, p + 1);
+        break;
+#ifdef USE_CASE_RANGE
+    case fixed_offset + 0x0 ... fixed_offset + 0xf:
+#else
+    case fixed_offset + 0x0:
+    case fixed_offset + 0x1:
+    case fixed_offset + 0x2:
+    case fixed_offset + 0x3:
+    case fixed_offset + 0x4:
+    case fixed_offset + 0x5:
+    case fixed_offset + 0x6:
+    case fixed_offset + 0x7:
+    case fixed_offset + 0x8:
+    case fixed_offset + 0x9:
+    case fixed_offset + 0xa:
+    case fixed_offset + 0xb:
+    case fixed_offset + 0xc:
+    case fixed_offset + 0xd:
+    case fixed_offset + 0xe:
+    case fixed_offset + 0xf:
+#endif
+        ++*off;
+        size = ((unsigned int)*p) & 0x0f;
+        break;
+    default:
+        PyErr_SetString(PyExc_ValueError, "Unexpected type header on stream");
+        return -1;
+    }
+    unpack_callback_uint32(&ctx->user, size, &ctx->stack[0].obj);
+    return 1;
+}
+
Index: msgpack-python-0.4.6/msgpack/unpack_template.h
===================================================================
--- msgpack-python-0.4.6.orig/msgpack/unpack_template.h
+++ msgpack-python-0.4.6/msgpack/unpack_template.h
@@ -71,8 +71,7 @@ static inline PyObject* unpack_data(unpa
 }
 
 
-template <bool construct>
-static inline int unpack_execute(unpack_context* ctx, const char* data, size_t len, size_t* off)
+static inline int unpack_execute(bool construct, unpack_context* ctx, const char* data, size_t len, size_t* off)
 {
     assert(len >= *off);
 
@@ -397,6 +396,7 @@ _end:
 #undef construct_cb
 }
 
+#undef NEXT_CS
 #undef SWITCH_RANGE_BEGIN
 #undef SWITCH_RANGE
 #undef SWITCH_RANGE_DEFAULT
@@ -408,68 +408,27 @@ _end:
 #undef again_fixed_trail_if_zero
 #undef start_container
 
-template <unsigned int fixed_offset, unsigned int var_offset>
-static inline int unpack_container_header(unpack_context* ctx, const char* data, size_t len, size_t* off)
-{
-    assert(len >= *off);
-    uint32_t size;
-    const unsigned char *const p = (unsigned char*)data + *off;
-
-#define inc_offset(inc) \
-    if (len - *off < inc) \
-        return 0; \
-    *off += inc;
-
-    switch (*p) {
-    case var_offset:
-        inc_offset(3);
-        size = _msgpack_load16(uint16_t, p + 1);
-        break;
-    case var_offset + 1:
-        inc_offset(5);
-        size = _msgpack_load32(uint32_t, p + 1);
-        break;
-#ifdef USE_CASE_RANGE
-    case fixed_offset + 0x0 ... fixed_offset + 0xf:
-#else
-    case fixed_offset + 0x0:
-    case fixed_offset + 0x1:
-    case fixed_offset + 0x2:
-    case fixed_offset + 0x3:
-    case fixed_offset + 0x4:
-    case fixed_offset + 0x5:
-    case fixed_offset + 0x6:
-    case fixed_offset + 0x7:
-    case fixed_offset + 0x8:
-    case fixed_offset + 0x9:
-    case fixed_offset + 0xa:
-    case fixed_offset + 0xb:
-    case fixed_offset + 0xc:
-    case fixed_offset + 0xd:
-    case fixed_offset + 0xe:
-    case fixed_offset + 0xf:
-#endif
-        ++*off;
-        size = ((unsigned int)*p) & 0x0f;
-        break;
-    default:
-        PyErr_SetString(PyExc_ValueError, "Unexpected type header on stream");
-        return -1;
-    }
-    unpack_callback_uint32(&ctx->user, size, &ctx->stack[0].obj);
-    return 1;
+static int unpack_construct(unpack_context *ctx, const char *data, size_t len, size_t *off) {
+    return unpack_execute(1, ctx, data, len, off);
+}
+static int unpack_skip(unpack_context *ctx, const char *data, size_t len, size_t *off) {
+    return unpack_execute(0, ctx, data, len, off);
 }
 
-#undef SWITCH_RANGE_BEGIN
-#undef SWITCH_RANGE
-#undef SWITCH_RANGE_DEFAULT
-#undef SWITCH_RANGE_END
-
-static const execute_fn unpack_construct = &unpack_execute<true>;
-static const execute_fn unpack_skip = &unpack_execute<false>;
-static const execute_fn read_array_header = &unpack_container_header<0x90, 0xdc>;
-static const execute_fn read_map_header = &unpack_container_header<0x80, 0xde>;
-
-#undef NEXT_CS
+#define unpack_container_header read_array_header
+#define fixed_offset 0x90
+#define var_offset 0xdc
+#include "unpack_container_header.h"
+#undef unpack_container_header
+#undef fixed_offset
+#undef var_offset
+
+#define unpack_container_header read_map_header
+#define fixed_offset 0x80
+#define var_offset 0xde
+#include "unpack_container_header.h"
+#undef unpack_container_header
+#undef fixed_offset
+#undef var_offset
 
 /* vim: set ts=4 sw=4 sts=4 expandtab  */
Index: msgpack-python-0.4.6/setup.py
===================================================================
--- msgpack-python-0.4.6.orig/setup.py
+++ msgpack-python-0.4.6/setup.py
@@ -20,7 +20,7 @@ except ImportError:
 
 def cythonize(src):
     sys.stderr.write("cythonize: %r\n" % (src,))
-    cython_compiler.compile([src], cplus=True, emit_linenums=True)
+    cython_compiler.compile([src], emit_linenums=True)
 
 def ensure_source(src):
     pyx = os.path.splitext(src)[0] + '.pyx'
@@ -71,6 +71,9 @@ else:
     Sdist = sdist
 
 libraries = []
+macros = []
+ext_modules = []
+
 if sys.platform == 'win32':
     libraries.append('ws2_32')

@@ -79,16 +82,15 @@ if sys.byteorder == 'big':
 else:
     macros = [('__LITTLE_ENDIAN__', '1')]
 
-ext_modules = []
 if not hasattr(sys, 'pypy_version_info'):
     ext_modules.append(Extension('msgpack._packer',
-                                 sources=['msgpack/_packer.cpp'],
+                                 sources=['msgpack/_packer.c'],
                                  libraries=libraries,
                                  include_dirs=['.'],
                                  define_macros=macros,
                                  ))
     ext_modules.append(Extension('msgpack._unpacker',
-                                 sources=['msgpack/_unpacker.cpp'],
+                                 sources=['msgpack/_unpacker.c'],
                                  libraries=libraries,
                                  include_dirs=['.'],
                                  define_macros=macros, 
