From 0a3901cf39dc2e290ed5646c5abcd1bfa3492eb5 Mon Sep 17 00:00:00 2001 From: David Capello Date: Sun, 21 Sep 2014 13:42:46 -0300 Subject: [PATCH] Add split_filename.cpp impl with base functions and std::string --- src/app/CMakeLists.txt | 1 + src/app/file/file.cpp | 133 +++++++------------------- src/app/file/split_filename.cpp | 73 ++++++++++++++ src/app/file/split_filename.h | 31 ++++++ src/app/file/split_filename_tests.cpp | 44 +++++++++ 5 files changed, 181 insertions(+), 101 deletions(-) create mode 100644 src/app/file/split_filename.cpp create mode 100644 src/app/file/split_filename.h create mode 100644 src/app/file/split_filename_tests.cpp diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index 5c8c21966..6b61dad62 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -123,6 +123,7 @@ add_library(app-lib file/palette_file.cpp file/pcx_format.cpp file/png_format.cpp + file/split_filename.cpp file/tga_format.cpp file_selector.cpp file_system.cpp diff --git a/src/app/file/file.cpp b/src/app/file/file.cpp index 95d4cbeee..1961d9a09 100644 --- a/src/app/file/file.cpp +++ b/src/app/file/file.cpp @@ -28,6 +28,7 @@ #include "app/file/file_format.h" #include "app/file/file_formats_manager.h" #include "app/file/format_options.h" +#include "app/file/split_filename.h" #include "app/modules/gui.h" #include "app/modules/palettes.h" #include "app/ui/status_bar.h" @@ -41,7 +42,6 @@ #include "raster/raster.h" #include "ui/alert.h" -#include #include namespace app { @@ -50,22 +50,20 @@ using namespace base; static FileOp* fop_new(FileOpType type, Context* context); static void fop_prepare_for_sequence(FileOp* fop); -static int split_filename(const char* filename, char* left, char* right, int* width); void get_readable_extensions(char* buf, int size) { FileFormatsList::iterator it = FileFormatsManager::instance()->begin(); FileFormatsList::iterator end = FileFormatsManager::instance()->end(); - /* clear the string */ - ustrncpy(buf, empty_string, size); + // Clear the string + strncpy(buf, "", size); - /* insert file format */ + // Insert file format for (; it != end; ++it) { if ((*it)->support(FILE_SUPPORT_LOAD)) { - if (ustrcmp(buf, empty_string) != 0) - ustrncat(buf, ",", size); - ustrncat(buf, (*it)->extensions(), size); + if (*buf) strncat(buf, ",", size); + strncat(buf, (*it)->extensions(), size); } } } @@ -75,15 +73,14 @@ void get_writable_extensions(char* buf, int size) FileFormatsList::iterator it = FileFormatsManager::instance()->begin(); FileFormatsList::iterator end = FileFormatsManager::instance()->end(); - /* clear the string */ - ustrncpy(buf, empty_string, size); + // Clear the string + strncpy(buf, "", size); - /* insert file format */ + // Insert file format for (; it != end; ++it) { if ((*it)->support(FILE_SUPPORT_SAVE)) { - if (ustrcmp(buf, empty_string) != 0) - ustrncat(buf, ",", size); - ustrncat(buf, (*it)->extensions(), size); + if (*buf) strncat(buf, ",", size); + strncat(buf, (*it)->extensions(), size); } } } @@ -180,22 +177,23 @@ FileOp* fop_to_load_document(Context* context, const char* filename, int flags) /* don't load the sequence (just the one file/one frame) */ if (!(flags & FILE_LOAD_SEQUENCE_NONE)) { - char buf[512], left[512], right[512]; + std::string left, right; int c, width, start_from; + char buf[512]; /* first of all, we must generate the list of files to load in the sequence... */ - /* check is this could be a sequence */ - start_from = split_filename(filename, left, right, &width); + // Check is this could be a sequence + start_from = split_filename(filename, left, right, width); if (start_from >= 0) { - /* try to get more file names */ + // Try to get more file names for (c=start_from+1; ; c++) { - /* get the next file name */ - usprintf(buf, "%s%0*d%s", left, width, c, right); + // Get the next file name + sprintf(buf, "%s%0*d%s", left.c_str(), width, c, right.c_str()); - /* if the file doesn't exist, we doesn't need more files to load */ - if (!exists(buf)) + // If the file doesn't exist, we doesn't need more files to load + if (!base::is_file(buf)) break; /* add this file name to the list */ @@ -208,14 +206,15 @@ FileOp* fop_to_load_document(Context* context, const char* filename, int flags) /* really want load all files? */ if ((fop->seq.filename_list.size() > 1) && (ui::Alert::show("Notice" - "<seq.filename_list[0]).c_str(), + base::get_file_name(fop->seq.filename_list[1]).c_str()) != 1)) { - /* if the user replies "Skip", we need just one file name (the - first one) */ + // If the user replies "Skip", we need just one file name + // (the first one). if (fop->seq.filename_list.size() > 1) { fop->seq.filename_list.erase(fop->seq.filename_list.begin()+1, fop->seq.filename_list.end()); @@ -365,10 +364,10 @@ FileOp* fop_to_save_document(Context* context, Document* document) } // To save more frames else { - char left[256], right[256]; + std::string left, right; int width, start_from; - start_from = split_filename(fop->document->filename().c_str(), left, right, &width); + start_from = split_filename(fop->document->filename().c_str(), left, right, width); if (start_from < 0) { start_from = 0; width = @@ -380,7 +379,7 @@ FileOp* fop_to_save_document(Context* context, Document* document) for (FrameNumber frame(0); framedocument->sprite()->totalFrames(); ++frame) { // Get the name for this frame char buf[4096]; - sprintf(buf, "%s%0*d%s", left, width, start_from+frame, right); + sprintf(buf, "%s%0*d%s", left.c_str(), width, start_from+frame, right.c_str()); fop->seq.filename_list.push_back(buf); } } @@ -755,9 +754,8 @@ void fop_error(FileOp *fop, const char *format, ...) { char buf_error[4096]; va_list ap; - va_start(ap, format); - uvszprintf(buf_error, sizeof(buf_error), format, ap); + vsnprintf(buf_error, sizeof(buf_error), format, ap); va_end(ap); // Concatenate the new error @@ -850,71 +848,4 @@ static void fop_prepare_for_sequence(FileOp* fop) fop->seq.format_options.reset(); } -// Splits a file-name like "my_ani0000.pcx" to "my_ani" and ".pcx", -// returning the number of the center; returns "-1" if the function -// can't split anything -static int split_filename(const char* filename, char* left, char* right, int* width) -{ - char *ptr, *ext; - char buf[16]; - int chr, ret; - - // Get the extension. - ext = get_extension(filename); - - // With extension. - if ((ext) && (*ext)) { - // Left side (the filename without the extension and without the '.'). - ext--; - *ext = 0; - ustrcpy(left, filename); - *ext = '.'; - - // Right side (the extension with the '.'). - ustrcpy(right, ext); - } - // Without extension (without right side). - else { - ustrcpy(left, filename); - ustrcpy(right, empty_string); - } - - // Remove all trailing numbers in the "left" side, and pass they to "buf". - - ptr = buf+9; - ptr[1] = 0; - ret = -1; - - if (width) - *width = 0; - - for (;;) { - chr = ugetat(left, -1); - if ((chr >= '0') && (chr <= '9')) { - ret = 0; - - if (ptr >= buf) { - *(ptr--) = chr; - - if (width) - (*width)++; - } - - uremove(left, -1); - } - else - break; - } - - // Convert the "buf" to integer and return it. - if (ret == 0) { - while (ptr >= buf) - *(ptr--) = '0'; - - ret = ustrtol(buf, NULL, 10); - } - - return ret; -} - } // namespace app diff --git a/src/app/file/split_filename.cpp b/src/app/file/split_filename.cpp new file mode 100644 index 000000000..d4ab11c7e --- /dev/null +++ b/src/app/file/split_filename.cpp @@ -0,0 +1,73 @@ +/* Aseprite + * Copyright (C) 2001-2014 David Capello + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "app/file/split_filename.h" +#include "base/convert_to.h" +#include "base/path.h" +#include "base/string.h" + +#include + +namespace app { + +// Splits a file-name like "my_ani0000.pcx" to "my_ani" and ".pcx", +// returning the number of the center; returns "-1" if the function +// can't split anything +int split_filename(const char* filename, std::string& left, std::string& right, int& width) +{ + left = base::join_path( + base::get_file_path(filename), + base::get_file_title(filename)); + right = base::get_file_extension(filename); + if (!right.empty()) + right.insert(right.begin(), '.'); + + // Remove all trailing numbers in the "left" side, and pass they to "buf". + std::string result_str; + width = 0; + for (;;) { + // Get the last utf-8 character + int chr = 0; + base::utf8_const_iterator begin(left.begin()), end(left.end()); + base::utf8_const_iterator it(begin), prev(begin); + for (; it != end; prev=it, ++it) + chr = *it; + + if ((chr >= '0') && (chr <= '9')) { + result_str.insert(result_str.begin(), chr); + width++; + + left.erase(std::distance(begin, prev)); + } + else + break; + } + + // Convert the "buf" to integer and return it. + if (!result_str.empty()) { + return base::convert_to(result_str); + } + else + return -1; +} + +} // namespace app diff --git a/src/app/file/split_filename.h b/src/app/file/split_filename.h new file mode 100644 index 000000000..217a7ee20 --- /dev/null +++ b/src/app/file/split_filename.h @@ -0,0 +1,31 @@ +/* Aseprite + * Copyright (C) 2001-2014 David Capello + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef APP_FILE_SPLIT_FILENAME_H_INCLUDED +#define APP_FILE_SPLIT_FILENAME_H_INCLUDED +#pragma once + +#include + +namespace app { + + int split_filename(const char* filename, std::string& left, std::string& right, int& width); + +} // namespace app + +#endif diff --git a/src/app/file/split_filename_tests.cpp b/src/app/file/split_filename_tests.cpp new file mode 100644 index 000000000..cdde3a22a --- /dev/null +++ b/src/app/file/split_filename_tests.cpp @@ -0,0 +1,44 @@ +/* Aseprite + * Copyright (C) 2001-2014 David Capello + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "tests/test.h" + +#include "app/file/split_filename.h" + +using namespace app; + +TEST(SplitFilename, Common) +{ + std::string left, right; + int width; + + EXPECT_EQ(1, split_filename("C:\\test\\a1.png", left, right, width)); + EXPECT_EQ("C:\\test\\a", left); + EXPECT_EQ(".png", right); + EXPECT_EQ(1, width); + + EXPECT_EQ(0, split_filename("file00.png", left, right, width)); + EXPECT_EQ("file", left); + EXPECT_EQ(".png", right); + EXPECT_EQ(2, width); + + EXPECT_EQ(32, split_filename("sprite1-0032", left, right, width)); + EXPECT_EQ("sprite1-", left); + EXPECT_EQ("", right); + EXPECT_EQ(4, width); +}