libmp3splt
|
00001 /********************************************************** 00002 * 00003 * libmp3splt -- library based on mp3splt, 00004 * for mp3/ogg splitting without decoding 00005 * 00006 * Copyright (c) 2002-2005 M. Trotta - <mtrotta@users.sourceforge.net> 00007 * Copyright (c) 2005-2011 Alexandru Munteanu - io_fx@yahoo.fr 00008 * 00009 * http://mp3splt.sourceforge.net 00010 * 00011 *********************************************************/ 00012 00013 /********************************************************** 00014 * 00015 * This program is free software; you can redistribute it and/or 00016 * modify it under the terms of the GNU General Public License 00017 * as published by the Free Software Foundation; either version 2 00018 * of the License, or (at your option) any later version. 00019 * 00020 * This program is distributed in the hope that it will be useful, 00021 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00023 * GNU General Public License for more details. 00024 * 00025 * You should have received a copy of the GNU General Public License 00026 * along with this program; if not, write to the Free Software 00027 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 00028 * 02111-1307, 00029 * USA. 00030 * 00031 *********************************************************/ 00032 00037 #include <stdio.h> 00038 #include <stdlib.h> 00039 #include <string.h> 00040 00041 #include <assert.h> 00042 #include <stdarg.h> 00043 00044 #include <ctype.h> 00045 00046 #include "splt.h" 00047 00048 void splt_su_replace_all_char(char *str, char to_replace, char replacement) 00049 { 00050 if (str == NULL) 00051 { 00052 return; 00053 } 00054 00055 int i = 0; 00056 for (i = 0;i < strlen(str);i++) 00057 { 00058 if (str[i] == to_replace) 00059 { 00060 str[i] = replacement; 00061 } 00062 } 00063 } 00064 00065 char *splt_su_replace_all(const char *str, char *to_replace, 00066 char *replacement, int *error) 00067 { 00068 if (str == NULL) 00069 { 00070 return NULL; 00071 } 00072 00073 char *new_str = NULL; 00074 int err = SPLT_OK; 00075 00076 if (to_replace == NULL || replacement == NULL) 00077 { 00078 int err = splt_su_copy(str, &new_str); 00079 if (err < 0) { *error = err; } 00080 return new_str; 00081 } 00082 00083 const char *ptr = str; 00084 const char *prev_ptr = ptr; 00085 while ((ptr = strstr(ptr, to_replace)) != NULL) 00086 { 00087 err = splt_su_append(&new_str, prev_ptr, ptr - prev_ptr, 00088 replacement, strlen(replacement), NULL); 00089 if (err != SPLT_OK) { goto error; } 00090 ptr += strlen(to_replace); 00091 prev_ptr = ptr; 00092 } 00093 00094 if (prev_ptr != NULL) 00095 { 00096 err = splt_su_append(&new_str, prev_ptr, (str + strlen(str)) - prev_ptr, NULL); 00097 if (err != SPLT_OK) { goto error; } 00098 } 00099 00100 return new_str; 00101 00102 error: 00103 if (new_str) 00104 { 00105 free(new_str); 00106 } 00107 *error = err; 00108 00109 return NULL; 00110 } 00111 00112 int splt_su_append_str(char **str, const char *to_append, ...) 00113 { 00114 int err = SPLT_OK; 00115 va_list ap; 00116 00117 va_start(ap, to_append); 00118 00119 while (to_append) 00120 { 00121 size_t to_append_size = strlen(to_append); 00122 err = splt_su_append(str, to_append, to_append_size, NULL); 00123 if (err < 0) { break; } 00124 to_append = va_arg(ap, const char *); 00125 } 00126 00127 va_end(ap); 00128 00129 return err; 00130 } 00131 00132 static int splt_su_append_one(char **str, const char *to_append, size_t to_append_size) 00133 { 00134 if (str == NULL || to_append == NULL || to_append[0] == '\0' || to_append_size == 0) 00135 { 00136 return SPLT_OK; 00137 } 00138 00139 size_t new_size = 0; 00140 00141 if (*str == NULL) 00142 { 00143 new_size = to_append_size + 1; 00144 *str = malloc(new_size); 00145 if (*str == NULL) 00146 { 00147 return SPLT_ERROR_CANNOT_ALLOCATE_MEMORY; 00148 } 00149 00150 *str[0] = '\0'; 00151 } 00152 else 00153 { 00154 new_size = to_append_size + strlen(*str) + 1; 00155 *str = realloc(*str, new_size); 00156 if (*str == NULL) 00157 { 00158 return SPLT_ERROR_CANNOT_ALLOCATE_MEMORY; 00159 } 00160 } 00161 00162 strncat(*str, to_append, to_append_size); 00163 00164 return SPLT_OK; 00165 } 00166 00167 int splt_su_append(char **str, const char *to_append, ...) 00168 { 00169 int err = SPLT_OK; 00170 va_list ap; 00171 00172 va_start(ap, to_append); 00173 00174 while (to_append) 00175 { 00176 size_t to_append_size = va_arg(ap, size_t); 00177 err = splt_su_append_one(str, to_append, to_append_size); 00178 if (err < 0) { break; } 00179 to_append = va_arg(ap, const char *); 00180 } 00181 00182 va_end(ap); 00183 00184 return err; 00185 } 00186 00187 void splt_su_free_replace(char **str, char *replacement) 00188 { 00189 if (!str) 00190 { 00191 return; 00192 } 00193 00194 if (*str) 00195 { 00196 free(*str); 00197 } 00198 00199 *str = replacement; 00200 } 00201 00202 int splt_su_copy(const char *src, char **dest) 00203 { 00204 if (!dest) 00205 { 00206 return SPLT_OK; 00207 } 00208 00209 if (*dest) 00210 { 00211 free(*dest); 00212 *dest = NULL; 00213 } 00214 00215 if (src == NULL) 00216 { 00217 *dest = NULL; 00218 return SPLT_OK; 00219 } 00220 00221 int length = strlen(src) + 1; 00222 if ((*dest = malloc(sizeof(char) * length)) == NULL) 00223 { 00224 return SPLT_ERROR_CANNOT_ALLOCATE_MEMORY; 00225 } 00226 00227 snprintf(*dest, length, "%s", src); 00228 00229 return SPLT_OK; 00230 } 00231 00232 static int splt_su_is_illegal_char(char c, int ignore_dirchar) 00233 { 00234 if ((ignore_dirchar) && (c == SPLT_DIRCHAR)) 00235 { 00236 return SPLT_FALSE; 00237 } 00238 00239 //for the sake of filename portability, we take the the windows illegal 00240 //characters (will be changed upon feature request) 00241 if ((c == '\\') || (c == '/') || (c == ':') || (c == '*') || 00242 (c == '?') || (c == '"') || (c == '<') || 00243 (c == '>') || (c == '|') || (c == '\r')) 00244 { 00245 return SPLT_TRUE; 00246 } 00247 00248 return SPLT_FALSE; 00249 } 00250 00251 static void splt_su_clean_string_(splt_state *state, char *s, int *error, int ignore_dirchar) 00252 { 00253 int i = 0, j=0; 00254 char *copy = NULL; 00255 if (s) 00256 { 00257 copy = strdup(s); 00258 if (copy) 00259 { 00260 for (i=0; i<=strlen(copy); i++) 00261 { 00262 if (! splt_su_is_illegal_char(copy[i], ignore_dirchar)) 00263 { 00264 s[j++] = copy[i]; 00265 } 00266 else 00267 { 00268 s[j++] = '_'; 00269 } 00270 } 00271 free(copy); 00272 copy = NULL; 00273 00274 // Trim string. I will never stop to be surprised about cddb strings dirtiness! ;-) 00275 for (i=strlen(s)-1; i >= 0; i--) 00276 { 00277 if (s[i]==' ') 00278 { 00279 s[i] = '\0'; 00280 } 00281 else 00282 { 00283 break; 00284 } 00285 } 00286 } 00287 else 00288 { 00289 *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY; 00290 } 00291 } 00292 } 00293 00294 void splt_su_clean_string(splt_state *state, char *s, int *error) 00295 { 00296 splt_su_clean_string_(state, s, error, SPLT_FALSE); 00297 } 00298 00299 char *splt_su_cut_spaces(char *c) 00300 { 00301 while (isspace(*c)) 00302 { 00303 c++; 00304 } 00305 00306 return c; 00307 } 00308 00309 char *splt_su_skip_spaces(char *c) 00310 { 00311 while (*c == ' ' || *c == '\t') 00312 { 00313 c++; 00314 } 00315 00316 return c; 00317 } 00318 00319 void splt_su_cut_spaces_from_end(char *c) 00320 { 00321 if (c == NULL || *c == '\0') 00322 { 00323 return; 00324 } 00325 00326 char *end = strchr(c, '\0'); 00327 if (!end) 00328 { 00329 return; 00330 } 00331 00332 end--; 00333 00334 while (isspace(*end)) 00335 { 00336 *end = '\0'; 00337 end--; 00338 } 00339 } 00340 00341 char *splt_su_trim_spaces(char *c) 00342 { 00343 splt_su_cut_spaces_from_end(c); 00344 return splt_su_cut_spaces(c); 00345 } 00346 00347 int splt_su_is_empty_line(const char *line) 00348 { 00349 if (!line) 00350 { 00351 return SPLT_TRUE; 00352 } 00353 00354 size_t size = strlen(line); 00355 int i = 0; 00356 for (i = 0;i < size;i++) 00357 { 00358 if (!isspace(line[i])) 00359 { 00360 return SPLT_FALSE; 00361 } 00362 } 00363 00364 return SPLT_TRUE; 00365 } 00366 00367 void splt_su_line_to_unix(char *line) 00368 { 00369 size_t line_size = strlen(line); 00370 if (line_size > 1) 00371 { 00372 if (line[line_size-2] == '\r') 00373 { 00374 line[line_size-2] = '\n'; 00375 line[line_size-1] = '\0'; 00376 } 00377 } 00378 } 00379 00380 void splt_su_keep_path_and_remove_filename(char *path) 00381 { 00382 char *last_dirchar = strrchr(path, SPLT_DIRCHAR); 00383 if (last_dirchar == NULL) 00384 { 00385 return; 00386 } 00387 00388 *(last_dirchar+1) = '\0'; 00389 00390 #ifdef __WIN32__ 00391 if (!splt_w32_str_is_drive_root_directory(path)) 00392 { 00393 *last_dirchar = '\0'; 00394 } 00395 #else 00396 if (last_dirchar != path) 00397 { 00398 *last_dirchar = '\0'; 00399 } 00400 #endif 00401 } 00402 00403 const char *splt_su_get_fname_without_path(const char *filename) 00404 { 00405 char *c = NULL; 00406 while ((c = strchr(filename, SPLT_DIRCHAR)) != NULL) 00407 { 00408 filename = c + 1; 00409 } 00410 00411 return filename; 00412 } 00413 00414 char *splt_su_get_fname_without_path_and_extension(const char *filename, int *error) 00415 { 00416 const char *fname_without_path = splt_su_get_fname_without_path(filename); 00417 00418 char *fname_without_path_and_extension = NULL; 00419 int err = splt_su_copy(fname_without_path, &fname_without_path_and_extension); 00420 if (err < 0) { 00421 *error = err; 00422 return NULL; 00423 } 00424 00425 splt_su_cut_extension(fname_without_path_and_extension); 00426 00427 return fname_without_path_and_extension; 00428 } 00429 00430 char *splt_su_get_fname_with_path_and_extension(splt_state *state, int *error) 00431 { 00432 int err = SPLT_OK; 00433 char *output_fname_with_path = NULL; 00434 00435 int current_split = splt_t_get_current_split(state); 00436 const char *output_fname = splt_sp_get_splitpoint_name(state, current_split, error); 00437 00438 if (!output_fname) 00439 { 00440 char *stdout_str = NULL; 00441 err = splt_su_copy("-", &stdout_str); 00442 if (err < 0) { *error = err; } 00443 return stdout_str; 00444 } 00445 00446 if (strcmp(output_fname, "-") == 0) 00447 { 00448 char *result = NULL; 00449 err = splt_su_copy(output_fname, &result); 00450 if (err < 0) { goto error; } 00451 return result; 00452 } 00453 00454 const char *extension = splt_p_get_extension(state, &err); 00455 if (err < 0) { goto error; } 00456 00457 const char *new_filename_path = splt_t_get_new_filename_path(state); 00458 if (new_filename_path[0] == '\0') 00459 { 00460 err = splt_su_append_str(&output_fname_with_path, output_fname, 00461 extension, NULL); 00462 if (err < 0) { goto error; } 00463 } 00464 else 00465 { 00466 if (new_filename_path[strlen(new_filename_path)-1] == SPLT_DIRCHAR) 00467 { 00468 err = splt_su_append_str(&output_fname_with_path, new_filename_path, 00469 output_fname, extension, NULL); 00470 } 00471 else 00472 { 00473 err = splt_su_append_str(&output_fname_with_path, new_filename_path, 00474 SPLT_DIRSTR, output_fname, extension, NULL); 00475 } 00476 if (err < 0) { goto error; } 00477 } 00478 00479 const char *filename = splt_t_get_filename_to_split(state); 00480 if (splt_io_check_if_file(state, output_fname_with_path)) 00481 { 00482 if (splt_check_is_the_same_file(state, filename, output_fname_with_path, &err)) 00483 { 00484 splt_e_set_error_data(state,filename); 00485 err = SPLT_ERROR_INPUT_OUTPUT_SAME_FILE; 00486 goto error; 00487 } 00488 } 00489 00490 //TODO: warning if a file already exists 00491 00492 return output_fname_with_path; 00493 00494 error: 00495 if (output_fname_with_path) 00496 { 00497 free(output_fname_with_path); 00498 output_fname_with_path = NULL; 00499 } 00500 00501 *error = err; 00502 00503 return NULL; 00504 } 00505 00506 void splt_su_cut_extension(char *str) 00507 { 00508 char *point = strrchr(str , '.'); 00509 if (point) 00510 { 00511 *point = '\0'; 00512 } 00513 } 00514 00515 void splt_su_str_cut_last_char(char *str) 00516 { 00517 if (!str) 00518 { 00519 return; 00520 } 00521 00522 str[strlen(str)-1] = '\0'; 00523 } 00524 00525 double splt_su_str_line_to_double(const char *str) 00526 { 00527 if (!str) 00528 { 00529 return 0.0; 00530 } 00531 00532 while ((*str != '\0') && (isdigit(*str) == 0)) 00533 { 00534 str++; 00535 } 00536 00537 return atof(str); 00538 } 00539 00540 char *splt_su_get_file_with_output_path(splt_state *state, char *filename, int *error) 00541 { 00542 int err = SPLT_OK; 00543 char *new_fname = NULL; 00544 00545 if (filename == NULL) 00546 { 00547 return NULL; 00548 } 00549 00550 splt_su_clean_string(state, filename, error); 00551 if (error < 0) { return NULL; } 00552 00553 const char *path_of_split = splt_t_get_path_of_split(state); 00554 if (path_of_split) 00555 { 00556 if (path_of_split[strlen(path_of_split)] == SPLT_DIRCHAR) 00557 { 00558 splt_su_append_str(&new_fname, path_of_split, filename, NULL); 00559 if (err < 0) { *error = err; } 00560 return new_fname; 00561 } 00562 00563 splt_su_append_str(&new_fname, path_of_split, SPLT_DIRSTR, filename, NULL); 00564 if (err < 0) { *error = err; } 00565 return new_fname; 00566 } 00567 00568 err = splt_su_copy(filename, &new_fname); 00569 if (err < 0) { *error = err; } 00570 return new_fname; 00571 } 00572 00573 int splt_su_str_ends_with(const char *str1, const char *str2) 00574 { 00575 if (!str1 || !str2) 00576 { 00577 return SPLT_FALSE; 00578 } 00579 00580 int str1_end_index = strlen(str1) - 1; 00581 int str2_end_index = strlen(str2) - 1; 00582 00583 while (str1_end_index >= 0 && str2_end_index >= 0) 00584 { 00585 if (str1[str1_end_index] != str2[str2_end_index]) 00586 { 00587 return SPLT_FALSE; 00588 } 00589 00590 str1_end_index--; 00591 str2_end_index--; 00592 } 00593 00594 return SPLT_TRUE; 00595 } 00596 00597 char *splt_su_format_messagev(splt_state *state, const char *message, va_list ap) 00598 { 00599 int counter = 0; 00600 00601 int written_chars = 0; 00602 00603 int size = 255; 00604 char *mess = malloc(sizeof(char) * size); 00605 if (mess == NULL) 00606 { 00607 splt_d_send_memory_error_message(state); 00608 splt_e_error(SPLT_IERROR_CHAR, __func__, 0, _("not enough memory")); 00609 return NULL; 00610 } 00611 00612 while (counter < LONG_MAX) 00613 { 00614 written_chars = vsnprintf(mess, size, message, ap); 00615 00616 if ((written_chars > -1) && 00617 (written_chars+1 < size)) 00618 { 00619 break; 00620 } 00621 else { 00622 size += 255; 00623 } 00624 00625 if ((mess = realloc(mess, size)) == NULL) 00626 { 00627 free(mess); 00628 splt_d_send_memory_error_message(state); 00629 splt_e_error(SPLT_IERROR_CHAR, __func__, 0, _("not enough memory")); 00630 return NULL; 00631 } 00632 00633 counter++; 00634 } 00635 00636 return mess; 00637 } 00638 00639 char *splt_su_get_formatted_message(splt_state *state, char *message, ...) 00640 { 00641 char *mess = NULL; 00642 00643 va_list ap; 00644 va_start(ap, message); 00645 mess = splt_su_format_messagev(state, message, ap); 00646 va_end(ap); 00647 00648 return mess; 00649 } 00650 00651 int splt_su_str_line_has_digit(const char *str) 00652 { 00653 while (*str != '\0') 00654 { 00655 if (isdigit(*str)) 00656 { 00657 return SPLT_TRUE; 00658 } 00659 00660 str++; 00661 } 00662 00663 return SPLT_FALSE; 00664 } 00665 00666 static char *splt_su_str_to_func(const char *str, int (*conversion_func)(int), int *error) 00667 { 00668 int err = SPLT_OK; 00669 00670 if (!str) 00671 { 00672 return NULL; 00673 } 00674 00675 char *result = NULL; 00676 err = splt_su_copy(str, &result); 00677 if (err < 0) 00678 { 00679 *error = err; 00680 return NULL; 00681 } 00682 00683 int i = 0; 00684 for (i = 0;i < strlen(str);i++) 00685 { 00686 result[i] = conversion_func(str[i]); 00687 } 00688 00689 return result; 00690 } 00691 00692 00693 char *splt_su_convert(const char *str, splt_str_format format, int *error) 00694 { 00695 if (str == NULL) 00696 { 00697 return NULL; 00698 } 00699 00700 char *new_str = NULL; 00701 00702 int lastspace = 1; 00703 int i = 0; 00704 00705 if (format != SPLT_TO_LOWERCASE && format != SPLT_TO_UPPERCASE) 00706 { 00707 int err = splt_su_copy(str, &new_str); 00708 if (err < 0) 00709 { 00710 *error = err; 00711 return NULL; 00712 } 00713 } 00714 00715 switch (format) 00716 { 00717 case SPLT_NO_CONVERSION: 00718 return new_str; 00719 break; 00720 case SPLT_TO_LOWERCASE: 00721 return splt_su_str_to_func(str, tolower, error); 00722 break; 00723 case SPLT_TO_UPPERCASE: 00724 return splt_su_str_to_func(str, toupper, error); 00725 break; 00726 case SPLT_TO_FIRST_UPPERCASE: 00727 new_str[0] = toupper(new_str[0]); 00728 return new_str; 00729 break; 00730 case SPLT_TO_WORD_FIRST_UPPERCASE: 00731 for (i = 0; i < strlen(new_str); i++) 00732 { 00733 if (lastspace && new_str[i] != ' ') 00734 { 00735 new_str[i] = toupper(new_str[i]); 00736 } 00737 00738 if (new_str[i] == ' ') 00739 { 00740 lastspace = 1; 00741 } 00742 else 00743 { 00744 lastspace = 0; 00745 } 00746 } 00747 return new_str; 00748 break; 00749 } 00750 00751 return NULL; 00752 } 00753