diff options
Diffstat (limited to 'source/blender/blenlib')
32 files changed, 576 insertions, 275 deletions
diff --git a/source/blender/blenlib/BLI_alloca.h b/source/blender/blenlib/BLI_alloca.h new file mode 100644 index 00000000000..b93f5b7123e --- /dev/null +++ b/source/blender/blenlib/BLI_alloca.h @@ -0,0 +1,46 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __BLI_ALLOCA_H__ + +/** \file BLI_alloca.h + * \ingroup bli + * + * Defines alloca and utility macro BLI_array_alloca + */ + +/* BLI_array_alloca / alloca */ +#ifdef _MSC_VER +# define alloca _alloca +#endif + +#if defined(__MINGW32__) +# include <malloc.h> /* mingw needs for alloca() */ +#endif + +#if defined(__GNUC__) || defined(__clang__) +#define BLI_array_alloca(arr, realsize) \ + (typeof(arr))alloca(sizeof(*arr) * (realsize)) +#else +#define BLI_array_alloca(arr, realsize) \ + alloca(sizeof(*arr) * (realsize)) +#endif + +#endif /* __BLI_ALLOCA_H__ */ diff --git a/source/blender/blenlib/BLI_array.h b/source/blender/blenlib/BLI_array.h index 3fb50afdeac..ef5cb8bde04 100644 --- a/source/blender/blenlib/BLI_array.h +++ b/source/blender/blenlib/BLI_array.h @@ -40,11 +40,11 @@ #define _bli_array_totalsize_dynamic(arr) ( \ ((arr) == NULL) ? \ 0 : \ - MEM_allocN_len(arr) / sizeof(*arr) \ + MEM_allocN_len(arr) / sizeof(*(arr)) \ ) #define _bli_array_totalsize_static(arr) \ - (sizeof(_##arr##_static) / sizeof(*arr)) + (sizeof(_##arr##_static) / sizeof(*(arr))) #define _bli_array_totalsize(arr) ( \ (size_t) \ @@ -66,8 +66,9 @@ void _bli_array_grow_func(void **arr_p, const void *arr_static, /* -------------------------------------------------------------------- */ /* public defines */ +/* use sizeof(*(arr)) to ensure the array exists and is an array */ #define BLI_array_declare(arr) \ - int _##arr##_count = 0; \ + int _##arr##_count = ((void)(sizeof(*(arr))), 0); \ void *_##arr##_static = NULL /* this will use stack space, up to maxstatic array elements, before @@ -95,7 +96,7 @@ void _bli_array_grow_func(void **arr_p, const void *arr_static, (LIKELY(_bli_array_totalsize(arr) >= _##arr##_count + num) ? \ (void)0 /* do nothing */ : \ _bli_array_grow_func((void **)&(arr), _##arr##_static, \ - sizeof(*arr), _##arr##_count, num, \ + sizeof(*(arr)), _##arr##_count, num, \ "BLI_array." #arr), \ (void)0) /* msvc2008 needs this */ \ ), \ @@ -148,8 +149,8 @@ void _bli_array_grow_func(void **arr_p, const void *arr_static, /* only to prevent unused warnings */ #define BLI_array_fake_user(arr) \ - (void)_##arr##_count, \ - (void)_##arr##_static + ((void)_##arr##_count, \ + (void)_##arr##_static) /* -------------------------------------------------------------------- */ @@ -161,7 +162,7 @@ void _bli_array_grow_func(void **arr_p, const void *arr_static, * but use when the max size is known ahead of time */ #define BLI_array_fixedstack_declare(arr, maxstatic, realsize, allocstr) \ char _##arr##_static[maxstatic * sizeof(*(arr))]; \ - const int _##arr##_is_static = ((void *)_##arr##_static) != ( \ + const bool _##arr##_is_static = ((void *)_##arr##_static) != ( \ arr = ((realsize) <= maxstatic) ? \ (void *)_##arr##_static : \ MEM_mallocN(sizeof(*(arr)) * (realsize), allocstr) \ @@ -172,31 +173,4 @@ void _bli_array_grow_func(void **arr_p, const void *arr_static, MEM_freeN(arr); \ } (void)0 - -/* alloca */ -#ifdef _MSC_VER -# define alloca _alloca -#endif - -#if defined(__MINGW32__) -# include <malloc.h> /* mingw needs for alloca() */ -#endif - -#if defined(__GNUC__) || defined(__clang__) -#define BLI_array_alloca(arr, realsize) \ - (typeof(arr))alloca(sizeof(*arr) * (realsize)) - -#define BLI_array_alloca_and_count(arr, realsize) \ - (typeof(arr))alloca(sizeof(*arr) * (realsize)); \ - const int _##arr##_count = (realsize) - -#else -#define BLI_array_alloca(arr, realsize) \ - alloca(sizeof(*arr) * (realsize)) - -#define BLI_array_alloca_and_count(arr, realsize) \ - alloca(sizeof(*arr) * (realsize)); \ - const int _##arr##_count = (realsize) -#endif - #endif /* __BLI_ARRAY_H__ */ diff --git a/source/blender/blenlib/BLI_bitmap.h b/source/blender/blenlib/BLI_bitmap.h index 02e5d6bd797..ca98d28cc40 100644 --- a/source/blender/blenlib/BLI_bitmap.h +++ b/source/blender/blenlib/BLI_bitmap.h @@ -26,7 +26,7 @@ #ifndef __BLI_BITMAP_H__ #define __BLI_BITMAP_H__ -typedef unsigned int *BLI_bitmap; +typedef unsigned int BLI_bitmap; /* warning: the bitmap does not keep track of its own size or check * for out-of-bounds access */ @@ -48,7 +48,7 @@ typedef unsigned int *BLI_bitmap; /* allocate memory for a bitmap with '_tot' bits; free * with MEM_freeN() */ #define BLI_BITMAP_NEW(_tot, _alloc_string) \ - ((BLI_bitmap)MEM_callocN(BLI_BITMAP_SIZE(_tot), \ + ((BLI_bitmap *)MEM_callocN(BLI_BITMAP_SIZE(_tot), \ _alloc_string)) /* get the value of a single bit at '_index' */ diff --git a/source/blender/blenlib/BLI_buffer.h b/source/blender/blenlib/BLI_buffer.h index fe835e7cadc..879ef869653 100644 --- a/source/blender/blenlib/BLI_buffer.h +++ b/source/blender/blenlib/BLI_buffer.h @@ -53,7 +53,7 @@ enum { #define BLI_buffer_declare_static(type_, name_, flag_, static_count_) \ char name_ ## user; /* warn for free only */ \ - type_ *name_ ## _static_[static_count_]; \ + type_ name_ ## _static_[static_count_]; \ BLI_Buffer name_ = { \ /* clear the static memory if this is a calloc'd array */ \ ((void)((flag_ & BLI_BUFFER_USE_CALLOC) ? \ diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h index 930715b4bc6..3ad0e18c8d7 100644 --- a/source/blender/blenlib/BLI_ghash.h +++ b/source/blender/blenlib/BLI_ghash.h @@ -73,7 +73,7 @@ void *BLI_ghash_lookup(GHash *gh, const void *key); bool BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp); void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp); void *BLI_ghash_pop(GHash *gh, void *key, GHashKeyFreeFP keyfreefp); -bool BLI_ghash_haskey(GHash *gh, const void *key); +bool BLI_ghash_haskey(GHash *gh, const void *key); int BLI_ghash_size(GHash *gh); /* *** */ diff --git a/source/blender/blenlib/BLI_listbase.h b/source/blender/blenlib/BLI_listbase.h index 767f61b29dd..4c7ddf7ba66 100644 --- a/source/blender/blenlib/BLI_listbase.h +++ b/source/blender/blenlib/BLI_listbase.h @@ -72,7 +72,7 @@ void BLI_freelinkN(struct ListBase *listbase, void *vlink); void BLI_movelisttolist(struct ListBase *dst, struct ListBase *src); void BLI_duplicatelist(struct ListBase *dst, const struct ListBase *src); void BLI_reverselist(struct ListBase *lb); -void BLI_rotatelist(struct ListBase *lb, LinkData *vlink); +void BLI_rotatelist(struct ListBase *lb, void *vlink); /* create a generic list node containing link to provided data */ struct LinkData *BLI_genericNodeN(void *data); diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h index 96652c0e78d..f9671f57acd 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -75,7 +75,8 @@ void closest_to_line_segment_v2(float closest[2], const float p[2], const float float dist_to_plane_normalized_v3(const float p[3], const float plane_co[3], const float plane_no_unit[3]); float dist_to_plane_v3(const float p[3], const float plane_co[3], const float plane_no[3]); -float dist_to_line_segment_v3(const float p[3], const float l1[3], const float l2[3]); +float dist_squared_to_line_segment_v3(const float p[3], const float l1[3], const float l2[3]); +float dist_to_line_segment_v3(const float p[3], const float l1[3], const float l2[3]); float dist_to_line_v3(const float p[3], const float l1[3], const float l2[3]); float closest_to_line_v3(float r[3], const float p[3], const float l1[3], const float l2[3]); float closest_to_line_v2(float r[2], const float p[2], const float l1[2], const float l2[2]); diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h index 723122d7814..c305cc9a030 100644 --- a/source/blender/blenlib/BLI_math_matrix.h +++ b/source/blender/blenlib/BLI_math_matrix.h @@ -133,12 +133,12 @@ void normalize_m4_m4(float R[4][4], float A[4][4]); void orthogonalize_m3(float R[3][3], int axis); void orthogonalize_m4(float R[4][4], int axis); -int is_orthogonal_m3(float mat[3][3]); -int is_orthogonal_m4(float mat[4][4]); -int is_orthonormal_m3(float mat[3][3]); -int is_orthonormal_m4(float mat[4][4]); +bool is_orthogonal_m3(float mat[3][3]); +bool is_orthogonal_m4(float mat[4][4]); +bool is_orthonormal_m3(float mat[3][3]); +bool is_orthonormal_m4(float mat[4][4]); -int is_uniform_scaled_m3(float mat[3][3]); +bool is_uniform_scaled_m3(float mat[3][3]); void adjoint_m2_m2(float R[2][2], float A[2][2]); void adjoint_m3_m3(float R[3][3], float A[3][3]); @@ -175,7 +175,7 @@ void mat4_to_size(float r[3], float M[4][4]); void translate_m4(float mat[4][4], float tx, float ty, float tz); void rotate_m4(float mat[4][4], const char axis, const float angle); void rotate_m2(float mat[2][2], const float angle); - +void transform_pivot_set_m4(float mat[4][4], const float pivot[3]); void mat3_to_rot_size(float rot[3][3], float size[3], float mat3[3][3]); void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], float wmat[4][4]); @@ -194,8 +194,11 @@ void loc_axisangle_size_to_mat4(float R[4][4], void blend_m3_m3m3(float R[3][3], float A[3][3], float B[3][3], const float t); void blend_m4_m4m4(float R[4][4], float A[4][4], float B[4][4], const float t); -int is_negative_m3(float mat[3][3]); -int is_negative_m4(float mat[4][4]); +bool is_negative_m3(float mat[3][3]); +bool is_negative_m4(float mat[4][4]); + +bool is_zero_m3(float mat[3][3]); +bool is_zero_m4(float mat[4][4]); /*********************************** Other ***********************************/ diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h index 0df4de1f829..38b377c640e 100644 --- a/source/blender/blenlib/BLI_math_vector.h +++ b/source/blender/blenlib/BLI_math_vector.h @@ -116,6 +116,9 @@ MINLINE void mul_v3_v3v3(float r[3], const float a[3], const float b[3]); MINLINE void mul_v4_fl(float r[4], float f); MINLINE void mul_v4_v4fl(float r[3], const float a[3], float f); MINLINE float mul_project_m4_v3_zfac(float mat[4][4], const float co[3]); +MINLINE float dot_m3_v3_row_x(float M[3][3], const float a[3]); +MINLINE float dot_m3_v3_row_y(float M[3][3], const float a[3]); +MINLINE float dot_m3_v3_row_z(float M[3][3], const float a[3]); MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f); MINLINE void madd_v3_v3v3(float r[3], const float a[3], const float b[3]); @@ -240,6 +243,7 @@ void rotate_normalized_v3_v3v3fl(float v[3], const float p[3], const float axis[ void print_v2(const char *str, const float a[2]); void print_v3(const char *str, const float a[3]); void print_v4(const char *str, const float a[4]); +void print_vn(const char *str, const float v[], const int n); MINLINE void normal_short_to_float_v3(float r[3], const short n[3]); MINLINE void normal_float_to_short_v3(short r[3], const float n[3]); diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h index e0a34e35acc..cb812fe8595 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -89,7 +89,18 @@ void BLI_make_existing_file(const char *name); void BLI_split_dirfile(const char *string, char *dir, char *file, const size_t dirlen, const size_t filelen); void BLI_split_dir_part(const char *string, char *dir, const size_t dirlen); void BLI_split_file_part(const char *string, char *file, const size_t filelen); -void BLI_join_dirfile(char *string, const size_t maxlen, const char *dir, const char *file); +void BLI_path_append(char *__restrict dst, const size_t maxlen, + const char *__restrict file) +#ifdef __GNUC__ +__attribute__((nonnull)) +#endif +; +void BLI_join_dirfile(char *__restrict string, const size_t maxlen, + const char *__restrict dir, const char *__restrict file) +#ifdef __GNUC__ +__attribute__((nonnull)) +#endif +; const char *BLI_path_basename(const char *path); typedef enum bli_rebase_state { diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h index c6f0bc49c9b..4816ac19fce 100644 --- a/source/blender/blenlib/BLI_string.h +++ b/source/blender/blenlib/BLI_string.h @@ -86,21 +86,21 @@ __attribute__((nonnull)) #endif ; -char *BLI_replacestr(char *__restrict str, const char *__restrict oldText, const char *__restrict newText) +char *BLI_replacestrN(const char *__restrict str, const char *__restrict substr_old, const char *__restrict substr_new) #ifdef __GNUC__ __attribute__((warn_unused_result)) __attribute__((nonnull)) #endif ; -size_t BLI_snprintf(char *__restrict buffer, size_t len, const char *__restrict format, ...) +size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format, ...) #ifdef __GNUC__ __attribute__ ((format(printf, 3, 4))) __attribute__((nonnull)) #endif ; -size_t BLI_vsnprintf(char *__restrict buffer, size_t count, const char *__restrict format, va_list arg) +size_t BLI_vsnprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format, va_list arg) #ifdef __GNUC__ __attribute__ ((format(printf, 3, 0))) #endif diff --git a/source/blender/blenlib/BLI_string_utf8.h b/source/blender/blenlib/BLI_string_utf8.h index d20cbd2a91c..db32190494a 100644 --- a/source/blender/blenlib/BLI_string_utf8.h +++ b/source/blender/blenlib/BLI_string_utf8.h @@ -31,41 +31,57 @@ extern "C" { #endif -char *BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy); -char *BLI_strncat_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy); -int BLI_utf8_invalid_byte(const char *str, int length); -int BLI_utf8_invalid_strip(char *str, int length); +#ifdef __GNUC__ +# define ATTR_NONULL __attribute__((nonnull)) +# define ATTR_NONULL_FIRST __attribute__((nonnull(1))) +# define ATTR_UNUSED_RESULT __attribute__((warn_unused_result)) +#else +# define ATTR_NONULL +# define ATTR_NONULL_FIRST +# define ATTR_UNUSED_RESULT +#endif + +char *BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONULL; +char *BLI_strncat_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONULL; +int BLI_utf8_invalid_byte(const char *str, int length) ATTR_NONULL; +int BLI_utf8_invalid_strip(char *str, int length) ATTR_NONULL; -int BLI_str_utf8_size(const char *p); /* warning, can return -1 on bad chars */ -int BLI_str_utf8_size_safe(const char *p); +int BLI_str_utf8_size(const char *p) ATTR_NONULL; /* warning, can return -1 on bad chars */ +int BLI_str_utf8_size_safe(const char *p) ATTR_NONULL; /* copied from glib */ -unsigned int BLI_str_utf8_as_unicode(const char *p); -unsigned int BLI_str_utf8_as_unicode_and_size(const char *__restrict p, size_t *__restrict index); -unsigned int BLI_str_utf8_as_unicode_and_size_safe(const char *__restrict p, size_t *__restrict index); -unsigned int BLI_str_utf8_as_unicode_step(const char *__restrict p, size_t *__restrict index); +unsigned int BLI_str_utf8_as_unicode(const char *p) ATTR_NONULL; +unsigned int BLI_str_utf8_as_unicode_and_size(const char *__restrict p, size_t *__restrict index) ATTR_NONULL; +unsigned int BLI_str_utf8_as_unicode_and_size_safe(const char *__restrict p, size_t *__restrict index) ATTR_NONULL; +unsigned int BLI_str_utf8_as_unicode_step(const char *__restrict p, size_t *__restrict index) ATTR_NONULL; size_t BLI_str_utf8_from_unicode(unsigned int c, char *outbuf); -char *BLI_str_find_prev_char_utf8(const char *str, const char *p); -char *BLI_str_find_next_char_utf8(const char *p, const char *end); -char *BLI_str_prev_char_utf8(const char *p); +char *BLI_str_find_prev_char_utf8(const char *str, const char *p) ATTR_NONULL; +char *BLI_str_find_next_char_utf8(const char *p, const char *end) ATTR_NONULL_FIRST; +char *BLI_str_prev_char_utf8(const char *p) ATTR_NONULL; /* wchar_t functions, copied from blenders own font.c originally */ -size_t BLI_wstrlen_utf8(const wchar_t *src); -size_t BLI_strlen_utf8(const char *strc); -size_t BLI_strnlen_utf8(const char *start, const size_t maxlen); -size_t BLI_strncpy_wchar_as_utf8(char *__restrict dst, const wchar_t *__restrict src, const size_t maxcpy); -size_t BLI_strncpy_wchar_from_utf8(wchar_t *__restrict dst, const char *__restrict src, const size_t maxcpy); +size_t BLI_wstrlen_utf8(const wchar_t *src) ATTR_NONULL; +size_t BLI_strlen_utf8_ex(const char *strc, size_t *r_len_bytes) ATTR_NONULL; +size_t BLI_strlen_utf8(const char *strc) ATTR_NONULL; +size_t BLI_strnlen_utf8_ex(const char *strc, const size_t maxlen, size_t *r_len_bytes) ATTR_NONULL; +size_t BLI_strnlen_utf8(const char *strc, const size_t maxlen) ATTR_NONULL; +size_t BLI_strncpy_wchar_as_utf8(char *__restrict dst, const wchar_t *__restrict src, const size_t maxcpy) ATTR_NONULL; +size_t BLI_strncpy_wchar_from_utf8(wchar_t *__restrict dst, const char *__restrict src, const size_t maxcpy) ATTR_NONULL; /* count columns that character/string occupies, based on wcwidth.c */ int BLI_wcwidth(wchar_t ucs); -int BLI_wcswidth(const wchar_t *pwcs, size_t n); -int BLI_str_utf8_char_width(const char *p); /* warning, can return -1 on bad chars */ -int BLI_str_utf8_char_width_safe(const char *p); +int BLI_wcswidth(const wchar_t *pwcs, size_t n) ATTR_NONULL; +int BLI_str_utf8_char_width(const char *p) ATTR_NONULL; /* warning, can return -1 on bad chars */ +int BLI_str_utf8_char_width_safe(const char *p) ATTR_NONULL; #define BLI_UTF8_MAX 6 /* mem */ #define BLI_UTF8_WIDTH_MAX 2 /* columns */ #define BLI_UTF8_ERR ((unsigned int)-1) +#undef ATTR_NONULL +#undef ATTR_NONULL_FIRST +#undef ATTR_UNUSED_RESULT + #ifdef __cplusplus } #endif diff --git a/source/blender/blenlib/BLI_threads.h b/source/blender/blenlib/BLI_threads.h index 331cac3ed76..154986936a2 100644 --- a/source/blender/blenlib/BLI_threads.h +++ b/source/blender/blenlib/BLI_threads.h @@ -131,6 +131,18 @@ void BLI_rw_mutex_free(ThreadRWMutex *mutex); void BLI_rw_mutex_lock(ThreadRWMutex *mutex, int mode); void BLI_rw_mutex_unlock(ThreadRWMutex *mutex); +/* Ticket Mutex Lock + * + * This is a 'fair' mutex in that it will grant the lock to the first thread + * that requests it. */ + +typedef struct TicketMutex TicketMutex; + +TicketMutex *BLI_ticket_mutex_alloc(void); +void BLI_ticket_mutex_free(TicketMutex *ticket); +void BLI_ticket_mutex_lock(TicketMutex *ticket); +void BLI_ticket_mutex_unlock(TicketMutex *ticket); + /* ThreadedWorker * * A simple tool for dispatching work to a limited number of threads diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index 1d94ca9afbc..b6b69116e67 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -99,6 +99,7 @@ set(SRC intern/winstuff.c BLI_args.h + BLI_alloca.h BLI_array.h BLI_bitmap.h BLI_blenlib.h diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c index d30d3f3d256..14dfbcffebe 100644 --- a/source/blender/blenlib/intern/BLI_ghash.c +++ b/source/blender/blenlib/intern/BLI_ghash.c @@ -34,6 +34,7 @@ #include <string.h> #include <stdlib.h> +#include <limits.h> #include "MEM_guardedalloc.h" @@ -178,7 +179,8 @@ void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfree gh->nentries = 0; gh->nbuckets = hashsizes[gh->cursize]; - gh->buckets = MEM_recallocN(gh->buckets, gh->nbuckets * sizeof(*gh->buckets)); + MEM_freeN(gh->buckets); + gh->buckets = MEM_callocN(gh->nbuckets * sizeof(*gh->buckets), "buckets"); } /* same as above but return the value, @@ -255,22 +257,14 @@ void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreef GHashIterator *BLI_ghashIterator_new(GHash *gh) { GHashIterator *ghi = MEM_mallocN(sizeof(*ghi), "ghash iterator"); - ghi->gh = gh; - ghi->curEntry = NULL; - ghi->curBucket = (unsigned int)-1; - while (!ghi->curEntry) { - ghi->curBucket++; - if (ghi->curBucket == ghi->gh->nbuckets) - break; - ghi->curEntry = ghi->gh->buckets[ghi->curBucket]; - } + BLI_ghashIterator_init(ghi, gh); return ghi; } void BLI_ghashIterator_init(GHashIterator *ghi, GHash *gh) { ghi->gh = gh; ghi->curEntry = NULL; - ghi->curBucket = (unsigned int)-1; + ghi->curBucket = UINT_MAX; /* wraps to zero */ while (!ghi->curEntry) { ghi->curBucket++; if (ghi->curBucket == ghi->gh->nbuckets) diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index cd5c961d982..a4c72aa26b0 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -72,7 +72,7 @@ struct BVHTree { /* optimization, ensure we stay small */ BLI_STATIC_ASSERT((sizeof(void *) == 8 && sizeof(BVHTree) <= 48) || (sizeof(void *) == 4 && sizeof(BVHTree) <= 32), - "over sized"); + "over sized") typedef struct BVHOverlapData { BVHTree *tree1, *tree2; @@ -603,6 +603,7 @@ static void build_implicit_tree_helper(BVHTree *tree, BVHBuildHelper *data) data->branches_on_level[0] = 1; /* We could stop the loop first (but I am lazy to find out when) */ + /* note: this often causes integer overflow, may be worth avoiding? - campbell */ for (depth = 1; depth < 32; depth++) { data->branches_on_level[depth] = data->branches_on_level[depth - 1] * data->tree_type; data->leafs_per_child[depth] = data->leafs_per_child[depth - 1] / data->tree_type; diff --git a/source/blender/blenlib/intern/BLI_mempool.c b/source/blender/blenlib/intern/BLI_mempool.c index 87179a93e83..217a4b9d266 100644 --- a/source/blender/blenlib/intern/BLI_mempool.c +++ b/source/blender/blenlib/intern/BLI_mempool.c @@ -437,19 +437,22 @@ void *BLI_mempool_iterstep(BLI_mempool_iter *iter) void BLI_mempool_destroy(BLI_mempool *pool) { BLI_mempool_chunk *mpchunk = NULL; + BLI_mempool_chunk *mpchunk_next; if (pool->flag & BLI_MEMPOOL_SYSMALLOC) { - for (mpchunk = pool->chunks.first; mpchunk; mpchunk = mpchunk->next) { + for (mpchunk = pool->chunks.first; mpchunk; mpchunk = mpchunk_next) { + mpchunk_next = mpchunk->next; free(mpchunk->data); + free(mpchunk); } - BLI_freelist(&(pool->chunks)); free(pool); } else { - for (mpchunk = pool->chunks.first; mpchunk; mpchunk = mpchunk->next) { + for (mpchunk = pool->chunks.first; mpchunk; mpchunk = mpchunk_next) { + mpchunk_next = mpchunk->next; MEM_freeN(mpchunk->data); + MEM_freeN(mpchunk); } - BLI_freelistN(&(pool->chunks)); MEM_freeN(pool); } } diff --git a/source/blender/blenlib/intern/DLRB_tree.c b/source/blender/blenlib/intern/DLRB_tree.c index cb47f07574d..31b4b7cd4a5 100644 --- a/source/blender/blenlib/intern/DLRB_tree.c +++ b/source/blender/blenlib/intern/DLRB_tree.c @@ -539,9 +539,8 @@ DLRBT_Node *BLI_dlrbTree_add(DLRBT_Tree *tree, DLRBT_Comparator_FP cmp_cb, parNode->left = node; node->parent = parNode; + break; } - break; - case 1: /* add new node as right child */ { node = new_cb(data); @@ -549,15 +548,14 @@ DLRBT_Node *BLI_dlrbTree_add(DLRBT_Tree *tree, DLRBT_Comparator_FP cmp_cb, parNode->right = node; node->parent = parNode; + break; } - break; - default: /* update the duplicate node as appropriate */ { if (update_cb) update_cb(parNode, data); + break; } - break; } } else { diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c index 26fe0f21cd5..4809ba59aaf 100644 --- a/source/blender/blenlib/intern/fileops.c +++ b/source/blender/blenlib/intern/fileops.c @@ -199,7 +199,7 @@ bool BLI_file_touch(const char *file) { FILE *f = BLI_fopen(file, "r+b"); if (f != NULL) { - char c = getc(f); + int c = getc(f); rewind(f); putc(c, f); } @@ -445,7 +445,7 @@ static void join_dirfile_alloc(char **dst, size_t *alloc_len, const char *dir, c size_t len = strlen(dir) + strlen(file) + 1; if (*dst == NULL) - *dst = MEM_callocN(len + 1, "join_dirfile_alloc path"); + *dst = MEM_mallocN(len + 1, "join_dirfile_alloc path"); else if (*alloc_len < len) *dst = MEM_reallocN(*dst, len + 1); @@ -911,18 +911,15 @@ void BLI_dir_create_recursive(const char *dirname) char static_buf[MAXPATHLEN]; #endif char *tmp; - int needs_free; if (BLI_exists(dirname)) return; #ifdef MAXPATHLEN size = MAXPATHLEN; tmp = static_buf; - needs_free = 0; #else size = strlen(dirname) + 1; - tmp = MEM_callocN(size, "BLI_dir_create_recursive tmp"); - needs_free = 1; + tmp = MEM_callocN(size, __func__); #endif BLI_strncpy(tmp, dirname, size); @@ -934,8 +931,9 @@ void BLI_dir_create_recursive(const char *dirname) BLI_dir_create_recursive(tmp); } - if (needs_free) - MEM_freeN(tmp); +#ifndef MAXPATHLEN + MEM_freeN(tmp); +#endif mkdir(dirname, 0777); } diff --git a/source/blender/blenlib/intern/listbase.c b/source/blender/blenlib/intern/listbase.c index f060a2771fe..ded4f31ae05 100644 --- a/source/blender/blenlib/intern/listbase.c +++ b/source/blender/blenlib/intern/listbase.c @@ -557,14 +557,14 @@ void BLI_reverselist(ListBase *lb) /** * \param vlink Link to make first. */ -void BLI_rotatelist(ListBase *lb, LinkData *vlink) +void BLI_rotatelist(ListBase *lb, void *vlink) { /* make circular */ ((LinkData *)lb->first)->prev = lb->last; ((LinkData *)lb->last)->next = lb->first; lb->first = vlink; - lb->last = vlink->prev; + lb->last = ((LinkData *)vlink)->prev; ((LinkData *)lb->first)->prev = NULL; ((LinkData *)lb->last)->next = NULL; diff --git a/source/blender/blenlib/intern/math_color.c b/source/blender/blenlib/intern/math_color.c index 3f802c492c2..8cfe4706937 100644 --- a/source/blender/blenlib/intern/math_color.c +++ b/source/blender/blenlib/intern/math_color.c @@ -150,6 +150,7 @@ void rgb_to_ycc(float r, float g, float b, float *ly, float *lcb, float *lcr, in break; default: assert(!"invalid colorspace"); + break; } *ly = y; @@ -183,7 +184,8 @@ void ycc_to_rgb(float y, float cb, float cr, float *lr, float *lg, float *lb, in b = y + 1.772f * cb - 226.816f; break; default: - assert(!"invalid colorspace"); + BLI_assert(0); + break; } *lr = r / 255.0f; *lg = g / 255.0f; diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index ddf1c598a1c..0e7ff521ce8 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -324,21 +324,26 @@ float dist_to_plane_v3(const float p[3], const float plane_co[3], const float pl return line_point_factor_v3(p, plane_co, plane_co_other); } -/* distance v1 to line-piece v2-v3 in 3D */ -float dist_to_line_segment_v3(const float v1[3], const float v2[3], const float v3[3]) +/* distance v1 to line-piece l1-l2 in 3D */ +float dist_squared_to_line_segment_v3(const float p[3], const float l1[3], const float l2[3]) { float closest[3]; - closest_to_line_segment_v3(closest, v1, v2, v3); + closest_to_line_segment_v3(closest, p, l1, l2); - return len_v3v3(closest, v1); + return len_squared_v3v3(closest, p); +} + +float dist_to_line_segment_v3(const float p[3], const float l1[3], const float l2[3]) +{ + return sqrtf(dist_squared_to_line_segment_v3(p, l1, l2)); } -float dist_to_line_v3(const float v1[3], const float v2[3], const float v3[3]) +float dist_to_line_v3(const float v1[3], const float l1[3], const float l2[3]) { float closest[3]; - closest_to_line_v3(closest, v1, v2, v3); + closest_to_line_v3(closest, v1, l1, l2); return len_v3v3(closest, v1); } @@ -489,6 +494,7 @@ int isect_seg_seg_v2_point(const float v1[2], const float v2[2], const float v3[ float a1, a2, b1, b2, c1, c2, d; float u, v; const float eps = 0.000001f; + const float eps_sq = eps * eps; a1 = v2[0] - v1[0]; b1 = v4[0] - v3[0]; @@ -505,8 +511,8 @@ int isect_seg_seg_v2_point(const float v1[2], const float v2[2], const float v3[ float a[2], b[2], c[2]; float u2; - if (len_v2v2(v1, v2) == 0.0f) { - if (len_v2v2(v3, v4) > eps) { + if (equals_v2v2(v1, v2)) { + if (len_squared_v2v2(v3, v4) > eps_sq) { /* use non-point segment as basis */ SWAP(const float *, v1, v3); SWAP(const float *, v2, v4); @@ -1452,7 +1458,7 @@ bool isect_axial_line_tri_v3(const int axis, const float p1[3], const float p2[3 int isect_line_line_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3], float i1[3], float i2[3]) { float a[3], b[3], c[3], ab[3], cb[3], dir1[3], dir2[3]; - float d; + float d, div; sub_v3_v3v3(c, v3, v1); sub_v3_v3v3(a, v2, v1); @@ -1468,12 +1474,17 @@ int isect_line_line_v3(const float v1[3], const float v2[3], const float v3[3], cross_v3_v3v3(ab, a, b); d = dot_v3v3(c, ab); + div = dot_v3v3(ab, ab); + /* test zero length line */ + if (UNLIKELY(div == 0.0f)) { + return 0; + } /* test if the two lines are coplanar */ - if (d > -0.000001f && d < 0.000001f) { + else if (d > -0.000001f && d < 0.000001f) { cross_v3_v3v3(cb, c, b); - mul_v3_fl(a, dot_v3v3(cb, ab) / dot_v3v3(ab, ab)); + mul_v3_fl(a, dot_v3v3(cb, ab) / div); add_v3_v3v3(i1, v1, a); copy_v3_v3(i2, i1); @@ -1518,7 +1529,7 @@ bool isect_line_line_strict_v3(const float v1[3], const float v2[3], float vi[3], float *r_lambda) { float a[3], b[3], c[3], ab[3], cb[3], ca[3], dir1[3], dir2[3]; - float d; + float d, div; sub_v3_v3v3(c, v3, v1); sub_v3_v3v3(a, v2, v1); @@ -1534,15 +1545,20 @@ bool isect_line_line_strict_v3(const float v1[3], const float v2[3], cross_v3_v3v3(ab, a, b); d = dot_v3v3(c, ab); + div = dot_v3v3(ab, ab); + /* test zero length line */ + if (UNLIKELY(div == 0.0f)) { + return 0; + } /* test if the two lines are coplanar */ - if (d > -0.000001f && d < 0.000001f) { + else if (d > -0.000001f && d < 0.000001f) { float f1, f2; cross_v3_v3v3(cb, c, b); cross_v3_v3v3(ca, c, a); - f1 = dot_v3v3(cb, ab) / dot_v3v3(ab, ab); - f2 = dot_v3v3(ca, ab) / dot_v3v3(ab, ab); + f1 = dot_v3v3(cb, ab) / div; + f2 = dot_v3v3(ca, ab) / div; if (f1 >= 0 && f1 <= 1 && f2 >= 0 && f2 <= 1) @@ -2588,45 +2604,62 @@ static float mean_value_half_tan_v2(const float v1[2], const float v2[2], const void interp_weights_poly_v3(float *w, float v[][3], const int n, const float co[3]) { - /* TODO: t1 and t2 overlap each iter, we could call this only once per iter and reuse previous value */ - float totweight, t1, t2, len, *vmid, *vprev, *vnext; - int i, i_next, i_curr; + const float eps = 0.00001f; /* take care, low values cause [#36105] */ + const float eps_sq = eps * eps; + float *v_curr, *v_next; + float ht_prev, ht; /* half tangents */ + float totweight = 0.0f; + int i = 0; + bool vert_interp = false; bool edge_interp = false; - totweight = 0.0f; + v_curr = v[0]; + v_next = v[1]; - for (i = 0; i < n; i++) { - i_curr = i; - i_next = (i == n - 1) ? 0 : i + 1; + ht_prev = mean_value_half_tan_v3(co, v[n - 1], v_curr); - vmid = v[i]; - vprev = (i == 0) ? v[n - 1] : v[i - 1]; - vnext = v[i_next]; + while (i < n) { + const float len_sq = len_squared_v3v3(co, v_curr); /* Mark Mayer et al algorithm that is used here does not operate well if vertex is close * to borders of face. In that case, do simple linear interpolation between the two edge vertices */ - if (dist_to_line_segment_v3(co, vmid, vnext) < 10 * FLT_EPSILON) { + if (len_sq < eps_sq) { + vert_interp = true; + break; + } + else if (dist_squared_to_line_segment_v3(co, v_curr, v_next) < eps_sq) { edge_interp = true; break; } - t1 = mean_value_half_tan_v3(co, vprev, vmid); - t2 = mean_value_half_tan_v3(co, vmid, vnext); - - len = len_v3v3(co, vmid); - w[i] = (len != 0.0f) ? (t1 + t2) / len: 0.0f; + ht = mean_value_half_tan_v3(co, v_curr, v_next); + w[i] = (ht_prev + ht) / sqrtf(len_sq); totweight += w[i]; + + /* step */ + i++; + v_curr = v_next; + v_next = v[(i + 1) % n]; + + ht_prev = ht; } - if (edge_interp) { - float len_curr = len_v3v3(co, vmid); - float len_next = len_v3v3(co, vnext); + if (vert_interp) { + const int i_curr = i; + for (i = 0; i < n; i++) + w[i] = 0.0; + w[i_curr] = 1.0f; + } + else if (edge_interp) { + const int i_curr = i; + float len_curr = len_v3v3(co, v_curr); + float len_next = len_v3v3(co, v_next); float edge_len = len_curr + len_next; for (i = 0; i < n; i++) w[i] = 0.0; w[i_curr] = len_next / edge_len; - w[i_next] = len_curr / edge_len; + w[(i_curr + 1) % n] = len_curr / edge_len; } else { if (totweight != 0.0f) { @@ -2640,45 +2673,62 @@ void interp_weights_poly_v3(float *w, float v[][3], const int n, const float co[ void interp_weights_poly_v2(float *w, float v[][2], const int n, const float co[2]) { - /* TODO: t1 and t2 overlap each iter, we could call this only once per iter and reuse previous value */ - float totweight, t1, t2, len, *vmid, *vprev, *vnext; - int i, i_next, i_curr; + const float eps = 0.00001f; /* take care, low values cause [#36105] */ + const float eps_sq = eps * eps; + float *v_curr, *v_next; + float ht_prev, ht; /* half tangents */ + float totweight = 0.0f; + int i = 0; + bool vert_interp = false; bool edge_interp = false; - totweight = 0.0f; + v_curr = v[0]; + v_next = v[1]; - for (i = 0; i < n; i++) { - i_curr = i; - i_next = (i == n - 1) ? 0 : i + 1; + ht_prev = mean_value_half_tan_v2(co, v[n - 1], v_curr); - vmid = v[i]; - vprev = (i == 0) ? v[n - 1] : v[i - 1]; - vnext = v[i_next]; + while (i < n) { + const float len_sq = len_squared_v2v2(co, v_curr); /* Mark Mayer et al algorithm that is used here does not operate well if vertex is close * to borders of face. In that case, do simple linear interpolation between the two edge vertices */ - if (dist_to_line_segment_v2(co, vmid, vnext) < 10 * FLT_EPSILON) { + if (len_sq < eps_sq) { + vert_interp = true; + break; + } + else if (dist_squared_to_line_segment_v2(co, v_curr, v_next) < eps_sq) { edge_interp = true; break; } - t1 = mean_value_half_tan_v2(co, vprev, vmid); - t2 = mean_value_half_tan_v2(co, vmid, vnext); - - len = len_v2v2(co, vmid); - w[i] = (len != 0.0f) ? (t1 + t2) / len: 0.0f; + ht = mean_value_half_tan_v2(co, v_curr, v_next); + w[i] = (ht_prev + ht) / sqrtf(len_sq); totweight += w[i]; + + /* step */ + i++; + v_curr = v_next; + v_next = v[(i + 1) % n]; + + ht_prev = ht; } - if (edge_interp) { - float len_curr = len_v2v2(co, vmid); - float len_next = len_v2v2(co, vnext); + if (vert_interp) { + const int i_curr = i; + for (i = 0; i < n; i++) + w[i] = 0.0; + w[i_curr] = 1.0f; + } + else if (edge_interp) { + const int i_curr = i; + float len_curr = len_v2v2(co, v_curr); + float len_next = len_v2v2(co, v_next); float edge_len = len_curr + len_next; for (i = 0; i < n; i++) w[i] = 0.0; w[i_curr] = len_next / edge_len; - w[i_next] = len_curr / edge_len; + w[(i_curr + 1) % n] = len_curr / edge_len; } else { if (totweight != 0.0f) { diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c index 298abfa8c5e..99342c4d6dc 100644 --- a/source/blender/blenlib/intern/math_matrix.c +++ b/source/blender/blenlib/intern/math_matrix.c @@ -790,6 +790,7 @@ void orthogonalize_m3(float mat[3][3], int axis) normalize_v3(mat[2]); cross_v3_v3v3(mat[1], mat[2], mat[0]); } + break; case 1: if (dot_v3v3(mat[1], mat[0]) < 1) { cross_v3_v3v3(mat[2], mat[0], mat[1]); @@ -812,6 +813,7 @@ void orthogonalize_m3(float mat[3][3], int axis) normalize_v3(mat[0]); cross_v3_v3v3(mat[2], mat[0], mat[1]); } + break; case 2: if (dot_v3v3(mat[2], mat[0]) < 1) { cross_v3_v3v3(mat[1], mat[2], mat[0]); @@ -834,6 +836,10 @@ void orthogonalize_m3(float mat[3][3], int axis) normalize_v3(mat[0]); cross_v3_v3v3(mat[1], mat[2], mat[0]); } + break; + default: + BLI_assert(0); + break; } mul_v3_fl(mat[0], size[0]); mul_v3_fl(mat[1], size[1]); @@ -868,8 +874,8 @@ void orthogonalize_m4(float mat[4][4], int axis) normalize_v3(mat[2]); cross_v3_v3v3(mat[1], mat[2], mat[0]); } + break; case 1: - normalize_v3(mat[0]); if (dot_v3v3(mat[1], mat[0]) < 1) { cross_v3_v3v3(mat[2], mat[0], mat[1]); normalize_v3(mat[2]); @@ -891,6 +897,7 @@ void orthogonalize_m4(float mat[4][4], int axis) normalize_v3(mat[0]); cross_v3_v3v3(mat[2], mat[0], mat[1]); } + break; case 2: if (dot_v3v3(mat[2], mat[0]) < 1) { cross_v3_v3v3(mat[1], mat[2], mat[0]); @@ -913,13 +920,17 @@ void orthogonalize_m4(float mat[4][4], int axis) normalize_v3(mat[0]); cross_v3_v3v3(mat[1], mat[2], mat[0]); } + break; + default: + BLI_assert(0); + break; } mul_v3_fl(mat[0], size[0]); mul_v3_fl(mat[1], size[1]); mul_v3_fl(mat[2], size[2]); } -int is_orthogonal_m3(float m[3][3]) +bool is_orthogonal_m3(float m[3][3]) { int i, j; @@ -933,7 +944,7 @@ int is_orthogonal_m3(float m[3][3]) return 1; } -int is_orthogonal_m4(float m[4][4]) +bool is_orthogonal_m4(float m[4][4]) { int i, j; @@ -948,7 +959,7 @@ int is_orthogonal_m4(float m[4][4]) return 1; } -int is_orthonormal_m3(float m[3][3]) +bool is_orthonormal_m3(float m[3][3]) { if (is_orthogonal_m3(m)) { int i; @@ -963,7 +974,7 @@ int is_orthonormal_m3(float m[3][3]) return 0; } -int is_orthonormal_m4(float m[4][4]) +bool is_orthonormal_m4(float m[4][4]) { if (is_orthogonal_m4(m)) { int i; @@ -978,7 +989,7 @@ int is_orthonormal_m4(float m[4][4]) return 0; } -int is_uniform_scaled_m3(float m[3][3]) +bool is_uniform_scaled_m3(float m[3][3]) { const float eps = 1e-7; float t[3][3]; @@ -1207,16 +1218,19 @@ void mat4_to_size(float size[3], float mat[4][4]) float mat3_to_scale(float mat[3][3]) { /* unit length vector */ - float unit_vec[3] = {0.577350269189626f, 0.577350269189626f, 0.577350269189626f}; + float unit_vec[3]; + copy_v3_fl(unit_vec, 0.577350269189626f); mul_m3_v3(mat, unit_vec); return len_v3(unit_vec); } float mat4_to_scale(float mat[4][4]) { - float tmat[3][3]; - copy_m3_m4(tmat, mat); - return mat3_to_scale(tmat); + /* unit length vector */ + float unit_vec[3]; + copy_v3_fl(unit_vec, 0.577350269189626f); + mul_mat3_m4_v3(mat, unit_vec); + return len_v3(unit_vec); } void mat3_to_rot_size(float rot[3][3], float size[3], float mat3[3][3]) @@ -1360,6 +1374,28 @@ void rotate_m2(float mat[2][2], const float angle) mat[1][0] = -mat[0][1]; } +/** + * Scale or rotate around a pivot point, + * a convenience function to avoid having to do inline. + * + * Since its common to make a scale/rotation matrix that pivots around an arbitrary point. + * + * Typical use case is to make 3x3 matrix, copy to 4x4, then pass to this function. + */ +void transform_pivot_set_m4(float mat[4][4], const float pivot[3]) +{ + float tmat[4][4]; + + unit_m4(tmat); + + copy_v3_v3(tmat[3], pivot); + mul_m4_m4m4(mat, tmat, mat); + + /* invert the matrix */ + negate_v3(tmat[3]); + mul_m4_m4m4(mat, mat, tmat); +} + void blend_m3_m3m3(float out[3][3], float dst[3][3], float src[3][3], const float srcweight) { float srot[3][3], drot[3][3]; @@ -1405,20 +1441,34 @@ void blend_m4_m4m4(float out[4][4], float dst[4][4], float src[4][4], const floa loc_quat_size_to_mat4(out, floc, fquat, fsize); } -int is_negative_m3(float mat[3][3]) +bool is_negative_m3(float mat[3][3]) { float vec[3]; cross_v3_v3v3(vec, mat[0], mat[1]); return (dot_v3v3(vec, mat[2]) < 0.0f); } -int is_negative_m4(float mat[4][4]) +bool is_negative_m4(float mat[4][4]) { float vec[3]; cross_v3_v3v3(vec, mat[0], mat[1]); return (dot_v3v3(vec, mat[2]) < 0.0f); } +bool is_zero_m3(float mat[3][3]) +{ + return (is_zero_v3(mat[0]) && + is_zero_v3(mat[1]) && + is_zero_v3(mat[2])); +} +bool is_zero_m4(float mat[4][4]) +{ + return (is_zero_v4(mat[0]) && + is_zero_v4(mat[1]) && + is_zero_v4(mat[2]) && + is_zero_v4(mat[3])); +} + /* make a 4x4 matrix out of 3 transform components */ /* matrices are made in the order: scale * rot * loc */ /* TODO: need to have a version that allows for rotation order... */ diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c index 96664b776f0..9fd8c479d6e 100644 --- a/source/blender/blenlib/intern/math_rotation.c +++ b/source/blender/blenlib/intern/math_rotation.c @@ -857,7 +857,8 @@ void single_axis_angle_to_mat3(float mat[3][3], const char axis, const float ang mat[2][2] = 1.0f; break; default: - assert(0); + BLI_assert(0); + break; } } @@ -1816,7 +1817,7 @@ static int _axis_convert_lut[23][24] = { {0x408, 0x810, 0xA20, 0x228, 0x081, 0x891, 0x699, 0x2A9, 0x102, 0x50A, 0x71A, 0xB22, 0x4CB, 0x8D3, 0xAE3, 0x2EB, 0x144, 0x954, 0x75C, 0x36C, 0x045, 0x44D, 0x65D, 0xA65}, - }; +}; // _axis_convert_num = {'X': 0, 'Y': 1, 'Z': 2, '-X': 3, '-Y': 4, '-Z': 5} diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c index 78266c47170..ba0394dbc66 100644 --- a/source/blender/blenlib/intern/math_vector.c +++ b/source/blender/blenlib/intern/math_vector.c @@ -542,6 +542,16 @@ void print_v4(const char *str, const float v[4]) printf("%s: %.3f %.3f %.3f %.3f\n", str, v[0], v[1], v[2], v[3]); } +void print_vn(const char *str, const float v[], const int n) +{ + int i = 0; + printf("%s[%d]:", str, n); + while (i < n) { + printf(" %.3f", v[i++]); + } + printf("\n"); +} + void minmax_v3v3_v3(float min[3], float max[3], const float vec[3]) { if (min[0] > vec[0]) min[0] = vec[0]; diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c index d77b1ecf017..8e5040d983b 100644 --- a/source/blender/blenlib/intern/math_vector_inline.c +++ b/source/blender/blenlib/intern/math_vector_inline.c @@ -418,6 +418,21 @@ MINLINE float mul_project_m4_v3_zfac(float mat[4][4], const float co[3]) (mat[2][3] * co[2]) + mat[3][3]; } +/** + * Has the effect of mul_m3_v3(), on a single axis. + */ +MINLINE float dot_m3_v3_row_x(float M[3][3], const float a[3]) +{ + return M[0][0] * a[0] + M[1][0] * a[1] + M[2][0] * a[2]; +} +MINLINE float dot_m3_v3_row_y(float M[3][3], const float a[3]) +{ + return M[0][1] * a[0] + M[1][1] * a[1] + M[2][1] * a[2]; +} +MINLINE float dot_m3_v3_row_z(float M[3][3], const float a[3]) +{ + return M[0][2] * a[0] + M[1][2] * a[1] + M[2][2] * a[2]; +} MINLINE void madd_v2_v2fl(float r[2], const float a[2], float f) { diff --git a/source/blender/blenlib/intern/noise.c b/source/blender/blenlib/intern/noise.c index 6e52145c653..2f94e833e9d 100644 --- a/source/blender/blenlib/intern/noise.c +++ b/source/blender/blenlib/intern/noise.c @@ -1252,6 +1252,7 @@ void voronoi(float x, float y, float z, float *da, float *pa, float me, int dtyp case 0: default: distfunc = dist_Real; + break; } xi = (int)(floor(x)); @@ -1467,6 +1468,7 @@ float BLI_gNoise(float noisesize, float x, float y, float z, int hard, int noise x += 1; y += 1; z += 1; + break; } } @@ -1522,6 +1524,7 @@ float BLI_gTurbulence(float noisesize, float x, float y, float z, int oct, int h x += 1; y += 1; z += 1; + break; } if (noisesize != 0.0f) { @@ -1596,6 +1599,7 @@ float mg_fBm(float x, float y, float z, float H, float lacunarity, float octaves default: { noisefunc = orgBlenderNoiseS; + break; } } @@ -1667,6 +1671,7 @@ float mg_MultiFractal(float x, float y, float z, float H, float lacunarity, floa default: { noisefunc = orgBlenderNoiseS; + break; } } @@ -1734,6 +1739,7 @@ float mg_HeteroTerrain(float x, float y, float z, float H, float lacunarity, flo default: { noisefunc = orgBlenderNoiseS; + break; } } @@ -1808,6 +1814,7 @@ float mg_HybridMultiFractal(float x, float y, float z, float H, float lacunarity default: { noisefunc = orgBlenderNoiseS; + break; } } @@ -1884,6 +1891,7 @@ float mg_RidgedMultiFractal(float x, float y, float z, float H, float lacunarity default: { noisefunc = orgBlenderNoiseS; + break; } } @@ -1950,6 +1958,7 @@ float mg_VLNoise(float x, float y, float z, float distortion, int nbas1, int nba default: { noisefunc1 = orgBlenderNoiseS; + break; } } @@ -1985,6 +1994,7 @@ float mg_VLNoise(float x, float y, float z, float distortion, int nbas1, int nba default: { noisefunc2 = orgBlenderNoiseS; + break; } } diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 1e76a7f3164..2c06a812c8a 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -610,9 +610,8 @@ bool BLI_parent_dir(char *path) { static char parent_dir[] = {'.', '.', SEP, '\0'}; /* "../" or "..\\" */ char tmp[FILE_MAX + 4]; - BLI_strncpy(tmp, path, sizeof(tmp) - 4); - BLI_add_slash(tmp); - strcat(tmp, parent_dir); + + BLI_join_dirfile(tmp, sizeof(tmp), path, parent_dir); BLI_cleanup_dir(NULL, tmp); /* does all the work of normalizing the path for us */ if (!BLI_testextensie(tmp, parent_dir)) { @@ -696,8 +695,10 @@ bool BLI_path_frame(char *path, int frame, int digits) if (stringframe_chars(path, &ch_sta, &ch_end)) { /* warning, ch_end is the last # +1 */ char tmp[FILE_MAX]; - sprintf(tmp, "%.*s%.*d%s", ch_sta, path, ch_end - ch_sta, frame, path + ch_end); - strcpy(path, tmp); + BLI_snprintf(tmp, sizeof(tmp), + "%.*s%.*d%s", + ch_sta, path, ch_end - ch_sta, frame, path + ch_end); + BLI_strncpy(path, tmp, FILE_MAX); return true; } return false; @@ -1229,6 +1230,7 @@ const char *BLI_get_folder(int folder_id, const char *subfolder) default: BLI_assert(0); + break; } return path; @@ -1257,7 +1259,9 @@ const char *BLI_get_user_folder_notest(int folder_id, const char *subfolder) break; default: BLI_assert(0); + break; } + if ('\0' == path[0]) { return NULL; } @@ -1307,6 +1311,7 @@ const char *BLI_get_folder_version(const int id, const int ver, const bool do_ch path[0] = '\0'; /* in case do_check is false */ ok = false; BLI_assert(!"incorrect ID"); + break; } if (!ok && do_check) { @@ -1686,6 +1691,26 @@ void BLI_split_file_part(const char *string, char *file, const size_t filelen) } /** + * Append a filename to a dir, ensuring slash separates. + */ +void BLI_path_append(char *dst, const size_t maxlen, const char *file) +{ + size_t dirlen = BLI_strnlen(dst, maxlen); + + /* inline BLI_add_slash */ + if ((dirlen > 0) && (dst[dirlen - 1] != SEP)) { + dst[dirlen++] = SEP; + dst[dirlen] = '\0'; + } + + if (dirlen >= maxlen) { + return; /* fills the path */ + } + + BLI_strncpy(dst + dirlen, file, maxlen - dirlen); +} + +/** * Simple appending of filename to dir, does not check for valid path! * Puts result into *dst, which may be same area as *dir. */ @@ -1693,15 +1718,16 @@ void BLI_join_dirfile(char *dst, const size_t maxlen, const char *dir, const cha { size_t dirlen = BLI_strnlen(dir, maxlen); - if (dst != dir) { - if (dirlen == maxlen) { - memcpy(dst, dir, dirlen); - dst[dirlen - 1] = '\0'; - return; /* dir fills the path */ - } - else { - memcpy(dst, dir, dirlen + 1); - } + /* args can't match */ + BLI_assert(!ELEM(dst, dir, file)); + + if (dirlen == maxlen) { + memcpy(dst, dir, dirlen); + dst[dirlen - 1] = '\0'; + return; /* dir fills the path */ + } + else { + memcpy(dst, dir, dirlen + 1); } if (dirlen + 1 >= maxlen) { @@ -1718,10 +1744,6 @@ void BLI_join_dirfile(char *dst, const size_t maxlen, const char *dir, const cha return; /* fills the path */ } - if (file == NULL) { - return; - } - BLI_strncpy(dst + dirlen, file, maxlen - dirlen); } @@ -1837,7 +1859,7 @@ int BLI_rebase_path(char *abs, size_t abs_len, /* subdirectories relative to blend_dir */ BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, rel_dir); /* same subdirectories relative to dest_dir */ - BLI_join_dirfile(dest_path, sizeof(dest_path), dest_path, base); + BLI_path_append(dest_path, sizeof(dest_path), base); /* keeping original item basename */ } @@ -2058,7 +2080,7 @@ static void bli_where_am_i(char *fullname, const size_t maxlen, const char *name else { strncpy(filename, path, sizeof(filename)); } - BLI_join_dirfile(fullname, maxlen, fullname, name); + BLI_path_append(fullname, maxlen, name); if (add_win32_extension(filename)) { BLI_strncpy(fullname, filename, maxlen); break; diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c index 6b45c6f1cb3..34c6e632131 100644 --- a/source/blender/blenlib/intern/storage.c +++ b/source/blender/blenlib/intern/storage.c @@ -44,7 +44,7 @@ #if defined(__sun__) || defined(__sun) || defined(__NetBSD__) # include <sys/statvfs.h> /* Other modern unix os's should probably use this also */ -#elif !defined(__FreeBSD__) && !defined(linux) && (defined(__sparc) || defined(__sparc__)) +#elif !defined(__FreeBSD__) && !defined(__linux__) && (defined(__sparc) || defined(__sparc__)) # include <sys/statfs.h> #endif @@ -53,7 +53,7 @@ # include <sys/mount.h> #endif -#if defined(linux) || defined(__CYGWIN32__) || defined(__hpux) || defined(__GNU__) || defined(__GLIBC__) +#if defined(__linux__) || defined(__CYGWIN32__) || defined(__hpux) || defined(__GNU__) || defined(__GLIBC__) #include <sys/vfs.h> #endif @@ -194,13 +194,13 @@ double BLI_dir_free_space(const char *dir) strcpy(name, "/"); } -#if defined(__FreeBSD__) || defined(linux) || defined(__OpenBSD__) || defined(__APPLE__) || defined(__GNU__) || defined(__GLIBC__) +#if defined(__FreeBSD__) || defined(__linux__) || defined(__OpenBSD__) || defined(__APPLE__) || defined(__GNU__) || defined(__GLIBC__) if (statfs(name, &disk)) return(-1); #endif #if defined(__sun__) || defined(__sun) || defined(__NetBSD__) if (statvfs(name, &disk)) return(-1); -#elif !defined(__FreeBSD__) && !defined(linux) && (defined(__sparc) || defined(__sparc__)) +#elif !defined(__FreeBSD__) && !defined(__linux__) && (defined(__sparc) || defined(__sparc__)) /* WARNING - This may not be supported by geeneric unix os's - Campbell */ if (statfs(name, &disk, sizeof(struct statfs), 0)) return(-1); #endif @@ -388,17 +388,14 @@ static void bli_adddirstrings(struct BuildDirCtx *dir_ctx) */ st_size = file->s.st_size; - /* FIXME: Either change decimal prefixes to binary ones - * <http://en.wikipedia.org/wiki/Binary_prefix>, or change - * divisor factors from 1024 to 1000. */ if (st_size > 1024 * 1024 * 1024) { - BLI_snprintf(file->size, sizeof(file->size), "%.2f GB", ((double)st_size) / (1024 * 1024 * 1024)); + BLI_snprintf(file->size, sizeof(file->size), "%.2f GiB", ((double)st_size) / (1024 * 1024 * 1024)); } else if (st_size > 1024 * 1024) { - BLI_snprintf(file->size, sizeof(file->size), "%.1f MB", ((double)st_size) / (1024 * 1024)); + BLI_snprintf(file->size, sizeof(file->size), "%.1f MiB", ((double)st_size) / (1024 * 1024)); } else if (st_size > 1024) { - BLI_snprintf(file->size, sizeof(file->size), "%d KB", (int)(st_size / 1024)); + BLI_snprintf(file->size, sizeof(file->size), "%d KiB", (int)(st_size / 1024)); } else { BLI_snprintf(file->size, sizeof(file->size), "%d B", (int)st_size); diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index 03bed428c07..572b142d044 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -47,6 +47,8 @@ # pragma GCC diagnostic error "-Wsign-conversion" #endif +// #define DEBUG_STRSIZE + /** * Duplicates the first \a len bytes of cstring \a str * into a newly mallocN'd string and returns it. \a str @@ -85,15 +87,18 @@ char *BLI_strdup(const char *str) */ char *BLI_strdupcat(const char *__restrict str1, const char *__restrict str2) { - size_t len; - char *n; + /* include the NULL terminator of str2 only */ + const size_t str1_len = strlen(str1); + const size_t str2_len = strlen(str2) + 1; + char *str, *s; - len = strlen(str1) + strlen(str2); - n = MEM_mallocN(len + 1, "strdupcat"); - strcpy(n, str1); - strcat(n, str2); - - return n; + str = MEM_mallocN(str1_len + str2_len, "strdupcat"); + s = str; + + memcpy(s, str1, str1_len); s += str1_len; + memcpy(s, str2, str2_len); + + return str; } /** @@ -111,6 +116,10 @@ char *BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t size_t srclen = BLI_strnlen(src, maxncpy - 1); BLI_assert(maxncpy != 0); +#ifdef DEBUG_STRSIZE + memset(dst, 0xff, sizeof(*dst) * maxncpy); +#endif + memcpy(dst, src, srclen); dst[srclen] = '\0'; return dst; @@ -134,6 +143,10 @@ size_t BLI_strncpy_rlen(char *__restrict dst, const char *__restrict src, const size_t srclen = BLI_strnlen(src, maxncpy - 1); BLI_assert(maxncpy != 0); +#ifdef DEBUG_STRSIZE + memset(dst, 0xff, sizeof(*dst) * maxncpy); +#endif + memcpy(dst, src, srclen); dst[srclen] = '\0'; return srclen; @@ -149,21 +162,21 @@ size_t BLI_strcpy_rlen(char *__restrict dst, const char *__restrict src) /** * Portable replacement for #vsnprintf */ -size_t BLI_vsnprintf(char *__restrict buffer, size_t count, const char *__restrict format, va_list arg) +size_t BLI_vsnprintf(char *__restrict buffer, size_t maxncpy, const char *__restrict format, va_list arg) { size_t n; BLI_assert(buffer != NULL); - BLI_assert(count > 0); + BLI_assert(maxncpy > 0); BLI_assert(format != NULL); - n = (size_t)vsnprintf(buffer, count, format, arg); + n = (size_t)vsnprintf(buffer, maxncpy, format, arg); - if (n != -1 && n < count) { + if (n != -1 && n < maxncpy) { buffer[n] = '\0'; } else { - buffer[count - 1] = '\0'; + buffer[maxncpy - 1] = '\0'; } return n; @@ -172,13 +185,17 @@ size_t BLI_vsnprintf(char *__restrict buffer, size_t count, const char *__restri /** * Portable replacement for #snprintf */ -size_t BLI_snprintf(char *__restrict buffer, size_t count, const char *__restrict format, ...) +size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format, ...) { size_t n; va_list arg; +#ifdef DEBUG_STRSIZE + memset(dst, 0xff, sizeof(*dst) * maxncpy); +#endif + va_start(arg, format); - n = BLI_vsnprintf(buffer, count, format, arg); + n = BLI_vsnprintf(dst, maxncpy, format, arg); va_end(arg); return n; @@ -226,6 +243,7 @@ size_t BLI_strescape(char *__restrict dst, const char *__restrict src, const siz goto escape_finish; case '\\': case '"': + /* fall-through */ /* less common but should also be support */ case '\t': @@ -239,9 +257,10 @@ size_t BLI_strescape(char *__restrict dst, const char *__restrict src, const siz /* not enough space to escape */ break; } - /* intentionally pass through */ + /* fall-through */ default: *dst = *src; + break; } dst++; src++; @@ -286,34 +305,30 @@ char *BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict } /** + * string with all instances of substr_old replaced with substr_new, * Returns a copy of the cstring \a str into a newly mallocN'd - * string with all instances of oldText replaced with newText, * and returns it. * * \note A rather wasteful string-replacement utility, though this shall do for now... * Feel free to replace this with an even safe + nicer alternative * - * \param str The string to replace occurrences of oldText in - * \param oldText The text in the string to find and replace - * \param newText The text in the string to find and replace + * \param str The string to replace occurrences of substr_old in + * \param substr_old The text in the string to find and replace + * \param substr_new The text in the string to find and replace * \retval Returns the duplicated string */ -char *BLI_replacestr(char *__restrict str, const char *__restrict oldText, const char *__restrict newText) +char *BLI_replacestrN(const char *__restrict str, const char *__restrict substr_old, const char *__restrict substr_new) { DynStr *ds = NULL; - size_t lenOld = strlen(oldText); - char *match; - - /* sanity checks */ - if ((str == NULL) || (str[0] == 0)) - return NULL; - else if ((oldText == NULL) || (newText == NULL) || (oldText[0] == 0)) - return BLI_strdup(str); - + size_t len_old = strlen(substr_old); + const char *match; + + BLI_assert(substr_old[0] != '\0'); + /* while we can still find a match for the old substring that we're searching for, * keep dicing and replacing */ - while ( (match = strstr(str, oldText)) ) { + while ((match = strstr(str, substr_old))) { /* the assembly buffer only gets created when we actually need to rebuild the string */ if (ds == NULL) ds = BLI_dynstr_new(); @@ -322,39 +337,35 @@ char *BLI_replacestr(char *__restrict str, const char *__restrict oldText, const * copy the text up to this position and advance the current position in the string */ if (str != match) { - /* replace the token at the 'match' position with \0 so that the copied string will be ok, - * add the segment of the string from str to match to the buffer, then restore the value at match + /* add the segment of the string from str to match to the buffer, then restore the value at match */ - match[0] = 0; - BLI_dynstr_append(ds, str); - match[0] = oldText[0]; + BLI_dynstr_nappend(ds, str, (match - str)); /* now our current position should be set on the start of the match */ str = match; } /* add the replacement text to the accumulation buffer */ - BLI_dynstr_append(ds, newText); + BLI_dynstr_append(ds, substr_new); /* advance the current position of the string up to the end of the replaced segment */ - str += lenOld; + str += len_old; } /* finish off and return a new string that has had all occurrences of */ if (ds) { - char *newStr; + char *str_new; /* add what's left of the string to the assembly buffer - * - we've been adjusting str to point at the end of the replaced segments + * - we've been adjusting str to point at the end of the replaced segments */ - if (str != NULL) - BLI_dynstr_append(ds, str); + BLI_dynstr_append(ds, str); /* convert to new c-string (MEM_malloc'd), and free the buffer */ - newStr = BLI_dynstr_get_cstring(ds); + str_new = BLI_dynstr_get_cstring(ds); BLI_dynstr_free(ds); - return newStr; + return str_new; } else { /* just create a new copy of the entire string - we avoid going through the assembly buffer diff --git a/source/blender/blenlib/intern/string_utf8.c b/source/blender/blenlib/intern/string_utf8.c index b8dca95ae33..225b3c5538f 100644 --- a/source/blender/blenlib/intern/string_utf8.c +++ b/source/blender/blenlib/intern/string_utf8.c @@ -45,6 +45,8 @@ # pragma GCC diagnostic error "-Wsign-conversion" #endif +// #define DEBUG_STRSIZE + /* from libswish3, originally called u8_isvalid(), * modified to return the index of the bad character (byte index not utf). * http://svn.swish-e.org/libswish3/trunk/src/libswish3/utf8.c r3044 - campbell */ @@ -195,6 +197,10 @@ char *BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t BLI_assert(maxncpy != 0); +#ifdef DEBUG_STRSIZE + memset(dst, 0xff, sizeof(*dst) * maxncpy); +#endif + /* note: currently we don't attempt to deal with invalid utf8 chars */ BLI_STR_UTF8_CPY(dst, src, maxncpy); @@ -208,6 +214,10 @@ char *BLI_strncat_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy--; } +#ifdef DEBUG_STRSIZE + memset(dst, 0xff, sizeof(*dst) * maxncpy); +#endif + BLI_STR_UTF8_CPY(dst, src, maxncpy); return dst; @@ -220,11 +230,16 @@ char *BLI_strncat_utf8(char *__restrict dst, const char *__restrict src, size_t size_t BLI_strncpy_wchar_as_utf8(char *__restrict dst, const wchar_t *__restrict src, const size_t maxncpy) { + const size_t maxlen = maxncpy - 1; size_t len = 0; BLI_assert(maxncpy != 0); - while (*src && len < maxncpy) { /* XXX can still run over the buffer because utf8 size isn't known :| */ +#ifdef DEBUG_STRSIZE + memset(dst, 0xff, sizeof(*dst) * maxncpy); +#endif + + while (*src && len < maxlen) { /* XXX can still run over the buffer because utf8 size isn't known :| */ len += BLI_str_utf8_from_unicode((unsigned int)*src++, dst + len); } @@ -245,24 +260,16 @@ size_t BLI_wstrlen_utf8(const wchar_t *src) return len; } -/* this is very close to 'BLI_str_utf8_size' functionality, perhaps we should de-duplicate */ -/* size of UTF-8 character in bytes */ -static size_t strlen_utf8_char(const char *strc) +size_t BLI_strlen_utf8_ex(const char *strc, size_t *r_len_bytes) { - if ((*strc & 0xe0) == 0xc0) { - if ((strc[1] & 0x80) && (strc[1] & 0x40) == 0x00) - return 2; - } - else if ((*strc & 0xf0) == 0xe0) { - if ((strc[1] & strc[2] & 0x80) && ((strc[1] | strc[2]) & 0x40) == 0x00) - return 3; - } - else if ((*strc & 0xf8) == 0xf0) { - if ((strc[1] & strc[2] & strc[3] & 0x80) && ((strc[1] | strc[2] | strc[3]) & 0x40) == 0x00) - return 4; - } + size_t len; + const char *strc_orig = strc; - return 1; + for (len = 0; *strc; len++) + strc += BLI_str_utf8_size_safe(strc); + + *r_len_bytes = (size_t)(strc - strc_orig); + return len; } size_t BLI_strlen_utf8(const char *strc) @@ -270,8 +277,22 @@ size_t BLI_strlen_utf8(const char *strc) size_t len; for (len = 0; *strc; len++) - strc += strlen_utf8_char(strc); + strc += BLI_str_utf8_size_safe(strc); + + return len; +} + +size_t BLI_strnlen_utf8_ex(const char *strc, const size_t maxlen, size_t *r_len_bytes) +{ + size_t len; + const char *strc_orig = strc; + const char *strc_end = strc + maxlen; + + for (len = 0; *strc && strc < strc_end; len++) { + strc += BLI_str_utf8_size_safe(strc); + } + *r_len_bytes = (size_t)(strc - strc_orig); return len; } @@ -280,15 +301,13 @@ size_t BLI_strlen_utf8(const char *strc) * \param maxlen the string length (in bytes) * \return the unicode length (not in bytes!) */ -size_t BLI_strnlen_utf8(const char *start, const size_t maxlen) +size_t BLI_strnlen_utf8(const char *strc, const size_t maxlen) { - const char *strc = start; - const char *strc_end = start + maxlen; - size_t len; + const char *strc_end = strc + maxlen; for (len = 0; *strc && strc < strc_end; len++) { - strc += strlen_utf8_char(strc); + strc += BLI_str_utf8_size_safe(strc); } return len; @@ -296,13 +315,16 @@ size_t BLI_strnlen_utf8(const char *start, const size_t maxlen) size_t BLI_strncpy_wchar_from_utf8(wchar_t *__restrict dst_w, const char *__restrict src_c, const size_t maxncpy) { + const size_t maxlen = maxncpy - 1; size_t len = 0; - if (dst_w == NULL || src_c == NULL) { - return 0; - } + BLI_assert(maxncpy != 0); - while (*src_c && len < maxncpy) { +#ifdef DEBUG_STRSIZE + memset(dst_w, 0xff, sizeof(*dst_w) * maxncpy); +#endif + + while (*src_c && len != maxlen) { size_t step = 0; unsigned int unicode = BLI_str_utf8_as_unicode_and_size(src_c, &step); if (unicode != BLI_UTF8_ERR) { @@ -316,6 +338,9 @@ size_t BLI_strncpy_wchar_from_utf8(wchar_t *__restrict dst_w, const char *__rest dst_w++; len++; } + + *dst_w = 0; + return len; } diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c index e0ea3bbf685..2b6fb52c49c 100644 --- a/source/blender/blenlib/intern/threads.c +++ b/source/blender/blenlib/intern/threads.c @@ -508,6 +508,52 @@ void BLI_rw_mutex_free(ThreadRWMutex *mutex) MEM_freeN(mutex); } +/* Ticket Mutex Lock */ + +struct TicketMutex { + pthread_cond_t cond; + pthread_mutex_t mutex; + unsigned int queue_head, queue_tail; +}; + +TicketMutex *BLI_ticket_mutex_alloc(void) +{ + TicketMutex *ticket = MEM_callocN(sizeof(TicketMutex), "TicketMutex"); + + pthread_cond_init(&ticket->cond, NULL); + pthread_mutex_init(&ticket->mutex, NULL); + + return ticket; +} + +void BLI_ticket_mutex_free(TicketMutex *ticket) +{ + pthread_mutex_destroy(&ticket->mutex); + pthread_cond_destroy(&ticket->cond); + MEM_freeN(ticket); +} + +void BLI_ticket_mutex_lock(TicketMutex *ticket) +{ + unsigned int queue_me; + + pthread_mutex_lock(&ticket->mutex); + queue_me = ticket->queue_tail++; + + while (queue_me != ticket->queue_head) + pthread_cond_wait(&ticket->cond, &ticket->mutex); + + pthread_mutex_unlock(&ticket->mutex); +} + +void BLI_ticket_mutex_unlock(TicketMutex *ticket) +{ + pthread_mutex_lock(&ticket->mutex); + ticket->queue_head++; + pthread_cond_broadcast(&ticket->cond); + pthread_mutex_unlock(&ticket->mutex); +} + /* ************************************************ */ typedef struct ThreadedWorker { |