<commit_before>#ifndef COMMON_H
#define COMMON_H

/* Macros to ease some of the boilerplate */
VALUE generic_new(VALUE klass, void *ptr, VALUE conn,
                  RUBY_DATA_FUNC free_func);

#define generic_get(kind, v)                                            \
    do {                                                                \
        vir##kind##Ptr ptr;                                             \
        Data_Get_Struct(v, vir##kind, ptr);                             \
        if (!ptr)                                                       \
            rb_raise(rb_eArgError, #kind " has been freed");            \
        return ptr;                                                     \
    } while (0);

#define generic_free(kind, p)                                           \
    do {                                                                \
        int r;                                                          \
        r = vir##kind##Free((vir##kind##Ptr) p);                        \
        if (r < 0)                                                      \
            rb_raise(rb_eSystemCallError, # kind " free failed");       \
    } while(0);

VALUE create_error(VALUE error, const char* method, virConnectPtr conn);

/*
 * Code generating macros.
 *
 * We only generate function bodies, not the whole function
 * declaration.
 */

/* Generate a call to a function FUNC which returns a string. The Ruby
 * function will return the string on success and throw an exception on
 * error. The string returned by FUNC is freed if dealloc is true.
 */
#define gen_call_string(func, conn, dealloc, args...)                   \
    do {                                                                \
        const char *str;                                                \
        VALUE result;                                                   \
                                                                        \
        str = func(args);                                               \
        _E(str == NULL, create_error(e_Error, # func, conn));           \
                                                                        \
        result = rb_str_new2(str);                                      \
        if (dealloc)                                                    \
            xfree((void *) str);                                        \
        return result;                                                  \
    } while(0)

/* Generate a call to vir##KIND##Free and return Qnil. Set the the embedded
 * vir##KIND##Ptr to NULL. If that pointer is already NULL, do nothing.
 */
#define gen_call_free(kind, s)                                          \
    do {                                                                \
        vir##kind##Ptr ptr;                                             \
        Data_Get_Struct(s, vir##kind, ptr);                             \
        if (ptr != NULL) {                                              \
            int r = vir##kind##Free(ptr);                               \
            _E(r < 0, create_error(e_Error, "vir" #kind "Free", conn(s))); \
            DATA_PTR(s) = NULL;                                         \
        }                                                               \
        return Qnil;                                                    \
    } while (0)

/* Generate a call to a function FUNC which returns an int error, where -1
 * indicates error and 0 success. The Ruby function will return Qnil on
 * success and throw an exception on error.
 */
#define gen_call_void(func, conn, args...)                              \
    do {                                                                \
        int _r_##func;                                                  \
        _r_##func = func(args);                                         \
        _E(_r_##func < 0, create_error(e_Error, #func, conn));          \
        return Qnil;                                                    \
    } while(0)

/*
 * Generate a call to a virConnectNumOf... function. C is the Ruby VALUE
 * holding the connection and OBJS is a token indicating what objects to
 * get the number of, e.g. 'Domains'
 */
#define gen_conn_num_of(c, objs)                                        \
    do {                                                                \
        int result;                                                     \
        virConnectPtr conn = connect_get(c);                            \
                                                                        \
        result = virConnectNumOf##objs(conn);                           \
        _E(result < 0, create_error(e_RetrieveError, "virConnectNumOf" # objs, conn));                \
                                                                        \
        return INT2NUM(result);                                         \
    } while(0)

/*
 * Generate a call to a virConnectList... function. S is the Ruby VALUE
 * holding the connection and OBJS is a token indicating what objects to
 * get the number of, e.g. 'Domains' The list function must return an array
 * of strings, which is returned as a Ruby array
 */
#define gen_conn_list_names(s, objs)                                    \
    do {                                                                \
        int i, r, num;                                                  \
        char **names;                                                   \
        virConnectPtr conn = connect_get(s);                            \
        VALUE result;                                                   \
                                                                        \
        num = virConnectNumOf##objs(conn);                              \
        _E(num < 0, create_error(e_RetrieveError, "virConnectNumOf" # objs, conn));   \
        if (num == 0) {                                                 \
            /* if num is 0, don't call virConnectList* function */      \
            result = rb_ary_new2(num);                                  \
            return result;                                              \
        }                                                               \
        names = ALLOC_N(char *, num);                                   \
        r = virConnectList##objs(conn, names, num);                     \
        if (r < 0) {                                                    \
            xfree(names);                                                \
            _E(r < 0, create_error(e_RetrieveError, "virConnectList" # objs, conn));  \
        }                                                               \
                                                                        \
        result = rb_ary_new2(num);                                      \
        for (i=0; i<num; i++) {                                         \
            rb_ary_push(result, rb_str_new2(names[i]));                 \
            xfree(names[i]);                                             \
        }                                                               \
        xfree(names);                                                    \
        return result;                                                  \
    } while(0)

/* Generate a call to a function FUNC which returns an int; -1 indicates<commit_msg>Fix up gen_conn_list_names.<commit_after>#ifndef COMMON_H
#define COMMON_H

/* Macros to ease some of the boilerplate */
VALUE generic_new(VALUE klass, void *ptr, VALUE conn,
                  RUBY_DATA_FUNC free_func);

#define generic_get(kind, v)                                            \
    do {                                                                \
        vir##kind##Ptr ptr;                                             \
        Data_Get_Struct(v, vir##kind, ptr);                             \
        if (!ptr)                                                       \
            rb_raise(rb_eArgError, #kind " has been freed");            \
        return ptr;                                                     \
    } while (0);

#define generic_free(kind, p)                                           \
    do {                                                                \
        int r;                                                          \
        r = vir##kind##Free((vir##kind##Ptr) p);                        \
        if (r < 0)                                                      \
            rb_raise(rb_eSystemCallError, # kind " free failed");       \
    } while(0);

VALUE create_error(VALUE error, const char* method, virConnectPtr conn);

/*
 * Code generating macros.
 *
 * We only generate function bodies, not the whole function
 * declaration.
 */

/* Generate a call to a function FUNC which returns a string. The Ruby
 * function will return the string on success and throw an exception on
 * error. The string returned by FUNC is freed if dealloc is true.
 */
#define gen_call_string(func, conn, dealloc, args...)                   \
    do {                                                                \
        const char *str;                                                \
        VALUE result;                                                   \
                                                                        \
        str = func(args);                                               \
        _E(str == NULL, create_error(e_Error, # func, conn));           \
                                                                        \
        result = rb_str_new2(str);                                      \
        if (dealloc)                                                    \
            xfree((void *) str);                                        \
        return result;                                                  \
    } while(0)

/* Generate a call to vir##KIND##Free and return Qnil. Set the the embedded
 * vir##KIND##Ptr to NULL. If that pointer is already NULL, do nothing.
 */
#define gen_call_free(kind, s)                                          \
    do {                                                                \
        vir##kind##Ptr ptr;                                             \
        Data_Get_Struct(s, vir##kind, ptr);                             \
        if (ptr != NULL) {                                              \
            int r = vir##kind##Free(ptr);                               \
            _E(r < 0, create_error(e_Error, "vir" #kind "Free", conn(s))); \
            DATA_PTR(s) = NULL;                                         \
        }                                                               \
        return Qnil;                                                    \
    } while (0)

/* Generate a call to a function FUNC which returns an int error, where -1
 * indicates error and 0 success. The Ruby function will return Qnil on
 * success and throw an exception on error.
 */
#define gen_call_void(func, conn, args...)                              \
    do {                                                                \
        int _r_##func;                                                  \
        _r_##func = func(args);                                         \
        _E(_r_##func < 0, create_error(e_Error, #func, conn));          \
        return Qnil;                                                    \
    } while(0)

/*
 * Generate a call to a virConnectNumOf... function. C is the Ruby VALUE
 * holding the connection and OBJS is a token indicating what objects to
 * get the number of, e.g. 'Domains'
 */
#define gen_conn_num_of(c, objs)                                        \
    do {                                                                \
        int result;                                                     \
        virConnectPtr conn = connect_get(c);                            \
                                                                        \
        result = virConnectNumOf##objs(conn);                           \
        _E(result < 0, create_error(e_RetrieveError, "virConnectNumOf" # objs, conn));                \
                                                                        \
        return INT2NUM(result);                                         \
    } while(0)

/*
 * Generate a call to a virConnectList... function. S is the Ruby VALUE
 * holding the connection and OBJS is a token indicating what objects to
 * get the number of, e.g. 'Domains' The list function must return an array
 * of strings, which is returned as a Ruby array
 */
#define gen_conn_list_names(s, objs)                                    \
    do {                                                                \
        int i, r, num;                                                  \
        char **names;                                                   \
        virConnectPtr conn = connect_get(s);                            \
        VALUE result;                                                   \
                                                                        \
        num = virConnectNumOf##objs(conn);                              \
        _E(num < 0, create_error(e_RetrieveError, "virConnectNumOf" # objs, conn));   \
        if (num == 0) {                                                 \
            /* if num is 0, don't call virConnectList* function */      \
            result = rb_ary_new2(num);                                  \
            return result;                                              \
        }                                                               \
        names = ALLOC_N(char *, num);                                   \
        r = virConnectList##objs(conn, names, num);                     \
        if (r < 0) {                                                    \
            xfree(names);                                               \
            _E(r < 0, create_error(e_RetrieveError, "virConnectList" # objs, conn));  \
        }                                                               \
                                                                        \
        /* FIXME: if this fails, we'll leak names (and names[i]) */     \
        result = rb_ary_new2(num);                                      \
        for (i=0; i<num; i++) {                                         \
            /* FIXME: if this fails, we'll leak names (and names[i]) */ \
            rb_ary_push(result, rb_str_new2(names[i]));                 \
            xfree(names[i]);                                            \
        }                                                               \
        xfree(names);                                                   \
        return result;                                                  \
    } while(0)

/* Generate a call to a function FUNC which returns an int; -1 indicates
{'fraction_non_alphanumeric': 0.07314156646515645, 'fraction_numerical': 0.0033215970238490667, 'mean_word_length': 0.6150627615062761, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 226, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1263807', 'n_tokens_mistral': 2874, 'n_tokens_neox': 2821, 'n_words': 859}