1 /*
2  util.h - utility functions for interfacing with the various python APIs.
3 
4  This software may be used and distributed according to the terms of
5  the GNU General Public License, incorporated herein by reference.
6 */
7 
8 #ifndef _HG_UTIL_H_
9 #define _HG_UTIL_H_
10 
11 #include "compat.h"
12 
13 #if PY_MAJOR_VERSION >= 3
14 #define IS_PY3K
15 #endif
16 
17 /* helper to switch things like string literal depending on Python version */
18 #ifdef IS_PY3K
19 #define PY23(py2, py3) py3
20 #else
21 #define PY23(py2, py3) py2
22 #endif
23 
24 /* clang-format off */
25 typedef struct {
26 	PyObject_HEAD
27 	int flags;
28 	int mode;
29 	int size;
30 	int mtime_s;
31 	int mtime_ns;
32 } dirstateItemObject;
33 /* clang-format on */
34 
35 static const int dirstate_flag_wc_tracked = 1 << 0;
36 static const int dirstate_flag_p1_tracked = 1 << 1;
37 static const int dirstate_flag_p2_info = 1 << 2;
38 static const int dirstate_flag_mode_exec_perm = 1 << 3;
39 static const int dirstate_flag_mode_is_symlink = 1 << 4;
40 static const int dirstate_flag_has_fallback_exec = 1 << 5;
41 static const int dirstate_flag_fallback_exec = 1 << 6;
42 static const int dirstate_flag_has_fallback_symlink = 1 << 7;
43 static const int dirstate_flag_fallback_symlink = 1 << 8;
44 static const int dirstate_flag_expected_state_is_modified = 1 << 9;
45 static const int dirstate_flag_has_meaningful_data = 1 << 10;
46 static const int dirstate_flag_has_mtime = 1 << 11;
47 static const int dirstate_flag_mtime_second_ambiguous = 1 << 12;
48 static const int dirstate_flag_directory = 1 << 13;
49 static const int dirstate_flag_all_unknown_recorded = 1 << 14;
50 static const int dirstate_flag_all_ignored_recorded = 1 << 15;
51 
52 extern PyTypeObject dirstateItemType;
53 #define dirstate_tuple_check(op) (Py_TYPE(op) == &dirstateItemType)
54 
55 #ifndef MIN
56 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
57 #endif
58 /* VC9 doesn't include bool and lacks stdbool.h based on my searching */
59 #if defined(_MSC_VER) || __STDC_VERSION__ < 199901L
60 #define true 1
61 #define false 0
62 typedef unsigned char bool;
63 #else
64 #include <stdbool.h>
65 #endif
66 
_dict_new_presized(Py_ssize_t expected_size)67 static inline PyObject *_dict_new_presized(Py_ssize_t expected_size)
68 {
69 	/* _PyDict_NewPresized expects a minused parameter, but it actually
70 	   creates a dictionary that's the nearest power of two bigger than the
71 	   parameter. For example, with the initial minused = 1000, the
72 	   dictionary created has size 1024. Of course in a lot of cases that
73 	   can be greater than the maximum load factor Python's dict object
74 	   expects (= 2/3), so as soon as we cross the threshold we'll resize
75 	   anyway. So create a dictionary that's at least 3/2 the size. */
76 	return _PyDict_NewPresized(((1 + expected_size) / 2) * 3);
77 }
78 
79 /* Convert a PyInt or PyLong to a long. Returns false if there is an
80    error, in which case an exception will already have been set. */
pylong_to_long(PyObject * pylong,long * out)81 static inline bool pylong_to_long(PyObject *pylong, long *out)
82 {
83 	*out = PyLong_AsLong(pylong);
84 	/* Fast path to avoid hitting PyErr_Occurred if the value was obviously
85 	 * not an error. */
86 	if (*out != -1) {
87 		return true;
88 	}
89 	return PyErr_Occurred() == NULL;
90 }
91 
92 #endif /* _HG_UTIL_H_ */
93