2323#ifndef XY_H
2424#define XY_H
2525
26- #define _XY_Version "v0.2.1.0 -2025/10/06 "
26+ #define _XY_Version "v0.2.1.1 -2025/10/07 "
2727#define _XY_Maintain_URL "https://github.com/RubyMetric/chsrc/blob/dev/lib/xy.h"
2828#define _XY_Maintain_URL2 "https://gitee.com/RubyMetric/chsrc/blob/dev/lib/xy.h"
2929
@@ -217,6 +217,27 @@ xy_malloc0 (size_t size)
217217 * String
218218 ******************************************************/
219219
220+ /**
221+ * @brief 替换字符串指针并自动释放旧内存
222+ *
223+ * @param old_ptr 指向要被替换的字符串指针的指针 (char **)
224+ * @param new_str 新的字符串指针
225+ */
226+ static inline void
227+ xy_ptr_replace (char * * old_ptr , char * new_str )
228+ {
229+ if (old_ptr && * old_ptr )
230+ {
231+ char * temp = * old_ptr ;
232+ * old_ptr = new_str ;
233+ free (temp );
234+ }
235+ else if (old_ptr )
236+ {
237+ * old_ptr = new_str ;
238+ }
239+ }
240+
220241/**
221242 * @brief 将 str 中所有的 pat 字符串替换成 replace,返回一个全新的字符串;也可用作删除、缩小、扩张
222243 *
@@ -479,23 +500,23 @@ xy_streql (const char *str1, const char *str2)
479500}
480501
481502static bool
482- xy_streql_ic (const char * str1 , const char * str2 )
503+ xy_streql_ic (const char * str1 , const char * str2 )
483504{
484505 if (NULL == str1 || NULL == str2 )
485506 {
486507 return false;
487508 }
488509
489- size_t len1 = strlen (str1 );
490- size_t len2 = strlen (str2 );
510+ size_t len1 = strlen (str1 );
511+ size_t len2 = strlen (str2 );
491512 if (len1 != len2 )
492513 {
493514 return false;
494515 }
495516
496517 for (size_t i = 0 ; i < len1 ; i ++ )
497518 {
498- if (tolower (str1 [i ]) != tolower (str2 [i ]))
519+ if (tolower (str1 [i ]) != tolower (str2 [i ]))
499520 {
500521 return false;
501522 }
@@ -569,14 +590,16 @@ xy_str_start_with (const char *str, const char *prefix)
569590static char *
570591xy_str_delete_prefix (const char * str , const char * prefix )
571592{
572- char * new = xy_strdup (str );
573593 bool yes = xy_str_start_with (str , prefix );
574594 if (!yes )
575- return new ;
576-
577- size_t len = strlen (prefix );
578- char * cur = new + len ;
579- return cur ;
595+ {
596+ return xy_strdup (str );
597+ }
598+ else
599+ {
600+ size_t len = strlen (prefix );
601+ return xy_strdup (str + len );
602+ }
580603}
581604
582605/**
@@ -603,23 +626,26 @@ xy_str_delete_suffix (const char *str, const char *suffix)
603626static char *
604627xy_str_strip (const char * str )
605628{
606- char * new = xy_strdup (str );
629+ if (!str )
630+ xy_cant_be_null (str );
631+
607632
608- while (strchr ("\n\r\v\t\f " , new [0 ]))
609- {
610- new += 1 ;
611- }
633+ const char * start = str ;
634+ while (* start && strchr ("\n\r\v\t\f " , * start ))
635+ start ++ ;
612636
613- size_t len = strlen (new );
637+ if ('\0' == * start )
638+ return xy_strdup ("" );
614639
615- char * last = new + len - 1 ;
640+ const char * end = start + strlen (start ) - 1 ;
641+ while (end >= start && strchr ("\n\r\v\t\f " , * end ))
642+ end -- ;
616643
617- while (strchr ("\n\r\v\t\f " , * last ))
618- {
619- * last = '\0' ;
620- last -= 1 ;
621- }
622- return new ;
644+ size_t len = (size_t ) (end - start + 1 );
645+ char * ret = xy_malloc0 (len + 1 );
646+ memcpy (ret , start , len );
647+ ret [len ] = '\0' ;
648+ return ret ;
623649}
624650
625651typedef struct
@@ -733,7 +759,7 @@ xy_file_read (const char *path)
733759 buf [read_bytes ] = '\0' ;
734760
735761 char * formatted_str = xy_str_gsub (buf , "\r\n" , "\n" );
736- formatted_str = xy_str_gsub (formatted_str , "\r" , "\n" );
762+ xy_ptr_replace ( & formatted_str , xy_str_gsub (formatted_str , "\r" , "\n" ) );
737763
738764 free (buf );
739765
@@ -1152,13 +1178,19 @@ _xy_win_powershellv5_profile ()
11521178static bool
11531179xy_file_exist (const char * path )
11541180{
1155- const char * new_path = path ;
1181+ char * expanded_path = NULL ;
1182+ const char * check_path = path ;
1183+
11561184 if (xy_str_start_with (path , "~" ))
11571185 {
1158- new_path = xy_2strcat (xy_os_home , path + 1 );
1186+ expanded_path = xy_2strcat (xy_os_home , path + 1 );
1187+ check_path = expanded_path ;
11591188 }
1189+
11601190 // 0 即 F_OK
1161- return (0 == access (new_path , 0 )) ? true : false;
1191+ bool result = (0 == access (check_path , 0 )) ? true : false;
1192+ if (expanded_path ) free (expanded_path );
1193+ return result ;
11621194}
11631195
11641196/**
@@ -1168,12 +1200,14 @@ xy_file_exist (const char *path)
11681200static bool
11691201xy_dir_exist (const char * path )
11701202{
1203+ char * allocated_dir = NULL ;
11711204 const char * dir = path ;
11721205 if (xy .on_windows )
11731206 {
11741207 if (xy_str_start_with (path , "~" ))
11751208 {
1176- dir = xy_2strcat (xy_os_home , path + 1 );
1209+ allocated_dir = xy_2strcat (xy_os_home , path + 1 );
1210+ dir = allocated_dir ;
11771211 }
11781212 }
11791213
@@ -1183,29 +1217,32 @@ xy_dir_exist (const char *path)
11831217 // 也可以用 opendir() #include <dirent.h>
11841218 DWORD attr = GetFileAttributesA (dir );
11851219
1220+ bool result = false;
11861221 if (attr == INVALID_FILE_ATTRIBUTES )
11871222 {
11881223 // Q: 我们应该报错吗?
1189- return false;
1224+ result = false;
11901225 }
11911226 else if (attr & FILE_ATTRIBUTE_DIRECTORY )
11921227 {
1193- return true;
1228+ result = true;
11941229 }
11951230 else
11961231 {
1197- return false;
1232+ result = false;
11981233 }
1234+ if (allocated_dir ) free (allocated_dir );
1235+ return result ;
11991236#endif
12001237 }
12011238 else
12021239 {
1203- int status = system ( xy_2strcat ("test -d " , dir ) );
1204-
1205- if ( 0 == status )
1206- return true ;
1207- else
1208- return false ;
1240+ char * tmp_cmd = xy_2strcat ("test -d " , dir );
1241+ int status = system ( tmp_cmd );
1242+ free ( tmp_cmd );
1243+ bool result = ( 0 == status ) ;
1244+ if ( allocated_dir ) free ( allocated_dir );
1245+ return result ;
12091246 }
12101247
12111248 return false;
@@ -1228,13 +1265,17 @@ xy_normalize_path (const char *path)
12281265
12291266 if (xy_str_start_with (new , "~" ))
12301267 {
1231- new = xy_2strcat (xy_os_home , xy_str_delete_prefix (new , "~" ));
1268+ char * tmp = xy_str_delete_prefix (new , "~" );
1269+ char * joined = xy_2strcat (xy_os_home , tmp );
1270+ free (tmp );
1271+ xy_ptr_replace (& new , joined );
12321272 }
12331273
12341274 if (xy .on_windows )
1235- return xy_str_gsub (new , "/" , "\\" );
1236- else
1237- return new ;
1275+ {
1276+ xy_ptr_replace (& new , xy_str_gsub (new , "/" , "\\" ));
1277+ }
1278+ return new ;
12381279}
12391280
12401281
@@ -1251,10 +1292,10 @@ xy_parent_dir (const char *path)
12511292 char * dir = xy_normalize_path (path );
12521293
12531294 /* 不管是否为Windows,全部统一使用 / 作为路径分隔符,方便后续处理 */
1254- dir = xy_str_gsub (dir , "\\" , "/" );
1295+ xy_ptr_replace ( & dir , xy_str_gsub (dir , "\\" , "/" ) );
12551296
12561297 if (xy_str_end_with (dir , "/" ))
1257- dir = xy_str_delete_suffix (dir , "/" );
1298+ xy_ptr_replace ( & dir , xy_str_delete_suffix (dir , "/" ) );
12581299
12591300 char * last = NULL ;
12601301
@@ -1268,9 +1309,10 @@ xy_parent_dir (const char *path)
12681309
12691310 /* Windows上重新使用 \ 作为路径分隔符 */
12701311 if (xy .on_windows )
1271- return xy_str_gsub (dir , "/" , "\\" );
1272- else
1273- return dir ;
1312+ {
1313+ xy_ptr_replace (& dir , xy_str_gsub (dir , "/" , "\\" ));
1314+ }
1315+ return dir ;
12741316}
12751317
12761318
@@ -1297,7 +1339,7 @@ xy_detect_os ()
12971339 if (fp )
12981340 {
12991341 char buf [256 ] = {0 };
1300- fread (buf , 1 , sizeof (buf ) - 1 , fp );
1342+ fread (buf , 1 , sizeof (buf ) - 1 , fp );
13011343 fclose (fp );
13021344 if (strstr (buf , "Linux" ))
13031345 {
@@ -1332,9 +1374,10 @@ xy_detect_os ()
13321374 fp = popen ("uname -s" , "r" );
13331375 if (!fp )
13341376 {
1335- if (opendir ("/etc/rc.d" ))
1377+ DIR * bsd_dir = opendir ("/etc/rc.d" );
1378+ if (bsd_dir )
13361379 {
1337- closedir (d );
1380+ closedir (bsd_dir );
13381381 xy .on_bsd = true;
13391382 return ;
13401383 }
0 commit comments