stockpiles: more error handling & cleanup

* prevent crashes when the path doesn't exist
* remove duplicated functions
* sort file list case insensitively
develop
Casey Link 2014-12-04 10:47:17 +01:00
parent 1525823948
commit 2f4678eee5
3 changed files with 68 additions and 41 deletions

@ -72,6 +72,7 @@ void StockpileSerializer::enable_debug ( std::ostream&out )
bool StockpileSerializer::serialize_to_ostream ( std::ostream* output )
{
if ( output->fail( ) ) return false;
mBuffer.Clear();
write();
{
@ -84,11 +85,17 @@ bool StockpileSerializer::serialize_to_ostream ( std::ostream* output )
bool StockpileSerializer::serialize_to_file ( const std::string & file )
{
std::fstream output ( file, std::ios::out | std::ios::binary | std::ios::trunc );
if ( output.fail() )
{
*mOut << "ERROR: failed to open file for writing: " << file << endl;
return false;
}
return serialize_to_ostream ( &output );
}
bool StockpileSerializer::parse_from_istream ( std::istream* input )
{
if ( input->fail( ) ) return false;
mBuffer.Clear();
io::IstreamInputStream zero_copy_input ( input );
const bool res = mBuffer.ParseFromZeroCopyStream ( &zero_copy_input ) && input->eof();
@ -100,6 +107,11 @@ bool StockpileSerializer::parse_from_istream ( std::istream* input )
bool StockpileSerializer::unserialize_from_file ( const std::string & file )
{
std::fstream input ( file, std::ios::in | std::ios::binary );
if ( input.fail() )
{
*mOut << "ERROR: failed to open file for reading: " << file << endl;
return false;
}
return parse_from_istream ( &input );
}

@ -7,8 +7,12 @@
#include "df/creature_raw.h"
#include "df/plant_raw.h"
#include <string>
#include <algorithm>
#include <functional>
// os
#include <sys/stat.h>
// Utility Functions {{{
// A set of convenience functions for doing common lookups
@ -48,6 +52,29 @@ static size_t find_plant ( const std::string &plant_id )
return linear_index ( df::global::world->raws.plants.all, &df::plant_raw::id, plant_id );
}
struct less_than_no_case: public std::binary_function< char,char,bool >
{
bool operator () (char x, char y) const
{
return toupper( static_cast< unsigned char >(x)) < toupper( static_cast< unsigned char >(y));
}
};
static bool CompareNoCase(const std::string &a, const std::string &b)
{
return std::lexicographical_compare( a.begin(),a.end(), b.begin(),b.end(), less_than_no_case() );
}
/**
* Checks if the parameter has the dfstock extension.
* Doesn't check if the file exists or not.
*/
static bool is_dfstockfile ( const std::string& filename )
{
return filename.rfind ( ".dfstock" ) != std::string::npos;
}
// }}} utility Functions

@ -9,6 +9,7 @@
#include "../uicommon.h"
#include "StockpileUtils.h"
#include "StockpileSerializer.h"
@ -25,11 +26,6 @@
#include "df/global_objects.h"
#include "df/viewscreen_dwarfmodest.h"
// os
#include <sys/stat.h>
// stl
#include <functional>
#include <vector>
@ -102,15 +98,9 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <Plug
std::cerr << "world: " << sizeof ( df::world ) << " ui: " << sizeof ( df::ui )
<< " b_stock: " << sizeof ( building_stockpilest ) << endl;
if (!Filesystem::isdir("stocksettings"))
if ( !Filesystem::isdir ( "stocksettings" ) )
{
if (!Filesystem::mkdir("stocksettings"))
{
out.printerr("stockpiles: could not create stocksettings directory!\n");
return CR_FAILURE;
}
}
// ViewscreenStocks::reset();
return CR_OK;
}
@ -125,7 +115,6 @@ DFhackCExport command_result plugin_onstatechange ( color_ostream &out, state_ch
switch ( event )
{
case SC_MAP_LOADED:
// ViewscreenStocks::reset();
break;
default:
break;
@ -222,23 +211,6 @@ static bool loadstock_guard ( df::viewscreen *top )
}
}
static bool file_exists ( const std::string& filename )
{
struct stat buf;
if ( stat ( filename.c_str(), &buf ) != -1 )
{
return true;
}
return false;
}
static bool is_dfstockfile ( const std::string& filename )
{
return filename.rfind ( ".dfstock" ) != std::string::npos;
}
// exporting
static command_result savestock ( color_ostream &out, vector <string> & parameters )
{
@ -317,7 +289,7 @@ static command_result loadstock ( color_ostream &out, vector <string> & paramete
}
if ( !is_dfstockfile ( file ) ) file += ".dfstock";
if ( file.empty() || !file_exists ( file ) )
if ( file.empty() || !Filesystem::exists ( file ) )
{
out.printerr ( "loadstock: a .dfstock file is required to import\n" );
return CR_WRONG_USAGE;
@ -334,10 +306,11 @@ static command_result loadstock ( color_ostream &out, vector <string> & paramete
return CR_OK;
}
/**
* calls the lua function manage_settings() to kickoff the GUI
*/
bool manage_settings ( building_stockpilest *sp )
{
// Find strings representing the job to order, and the trigger condition.
// There might be a memory leak here; C++ is odd like that.
auto L = Lua::Core::State;
color_ostream_proxy out ( Core::getInstance().getConsole() );
@ -395,7 +368,6 @@ struct stockpiles_import_hook : public df::viewscreen_dwarfmodest
int left_margin = dims.menu_x1 + 1;
int x = left_margin;
int y = dims.y2 - 7;
int y2 = dims.y2 - 8;
int links = 0;
links += sp->links.give_to_pile.size();
@ -405,7 +377,6 @@ struct stockpiles_import_hook : public df::viewscreen_dwarfmodest
if ( links + 12 >= y )
{
y += 1;
y2 += 1;
}
OutputHotkeyString ( x, y, "Load/Save Settings", "l", true, left_margin, COLOR_WHITE, COLOR_LIGHTRED );
@ -477,6 +448,10 @@ static std::vector<std::string> list_dir ( const std::string &path, bool recursi
static std::vector<std::string> clean_dfstock_list ( const std::string &path )
{
if ( !Filesystem::exists ( path ) )
{
return std::vector<std::string>();
}
std::vector<std::string> files ( list_dir ( path, true) );
files.erase ( std::remove_if ( files.begin(), files.end(), [] ( const std::string &f )
{
@ -486,16 +461,23 @@ static std::vector<std::string> clean_dfstock_list ( const std::string &path )
{
return f.substr ( 0, f.find_last_of ( "." ) );
} );
std::sort ( files.begin(),files.end(), CompareNoCase );
return files;
}
static int stockpiles_list_settings ( lua_State *L )
{
auto path = luaL_checkstring ( L, 1 );
if ( !Filesystem::exists ( path ) )
{
lua_pushfstring ( L, "stocksettings path invalid: %s", path );
lua_error ( L );
return 0;
}
color_ostream &out = *Lua::GetOutput ( L );
if ( !Filesystem::isdir(path) )
{
lua_pushfstring ( L, "invalid directory: %s", path );
lua_pushfstring ( L, "stocksettings path invalid: %s", path );
lua_error ( L );
return 0;
}
@ -507,6 +489,11 @@ static int stockpiles_list_settings ( lua_State *L )
static void stockpiles_load ( color_ostream &out, std::string filename )
{
out << "stockpiles_load " << filename << " ";
if ( !Filesystem::exists ( filename ) )
{
out.printerr ( "invalid file: %s\n", filename.c_str() );
return;
}
std::vector<std::string> params;
params.push_back ( filename );
command_result r = loadstock ( out, params );
@ -524,9 +511,10 @@ static void stockpiles_save ( color_ostream &out, std::string filename )
out << " result = "<< r << endl;
}
DFHACK_PLUGIN_LUA_FUNCTIONS {
DFHACK_LUA_FUNCTION(stockpiles_load),
DFHACK_LUA_FUNCTION(stockpiles_save),
DFHACK_PLUGIN_LUA_FUNCTIONS
{
DFHACK_LUA_FUNCTION ( stockpiles_load ),
DFHACK_LUA_FUNCTION ( stockpiles_save ),
DFHACK_LUA_END
};