Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F84616764
all_io_files.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Mon, Sep 23, 22:53
Size
14 KB
Mime Type
text/x-c++
Expires
Wed, Sep 25, 22:53 (2 d)
Engine
blob
Format
Raw Data
Handle
21060513
Attached To
rSPECMICP SpecMiCP / ReactMiCP
all_io_files.cpp
View Options
/* =============================================================================
Copyright (c) 2014 - 2017
F. Georget <fabieng@princeton.edu> Princeton University
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
============================================================================= */
#include "all_io_files.hpp"
#include "specmicp_common/io/yaml.hpp"
#include "specmicp_common/filesystem.hpp"
#include "specmicp_common/dateandtime.hpp"
#include "specmicp_common/log.hpp"
#include <iostream>
#ifndef SPC_DOXYGEN_SHOULD_SKIP_THIS
#define SPC_IO_A_CREATION "creation_time"
#define SPC_IO_A_MODIFICATION "modification_time"
#define SPC_IO_A_CLI "command_line"
#define SPC_IO_S_INPUT "input"
#define SPC_IO_S_SOLUTION "solution"
#define SPC_IO_S_DATABASE "database"
#define SPC_IO_S_LOGS "logs"
#define SPC_IO_A_NAME "name"
#define SPC_IO_A_PATH "path"
#define SPC_IO_A_COMMENT "comment"
#define SPC_IO_A_TYPE "type"
#define SPC_IO_V_INPUT "input"
#define SPC_IO_V_OUTPUT "output"
#define SPC_IO_V_IN_OUT_PUT "input_output"
#endif
// SPC_DOXYGEN_SHOULD_SKIP_THIS
namespace
specmicp
{
namespace
io
{
struct
AllIOFiles
::
AllIOFilesImpl
{
public
:
AllIOFilesImpl
(
std
::
string
filepath
,
AllIOFilesMode
mode
);
std
::
time_t
get_creation_time
();
std
::
time_t
get_last_modification_time
();
std
::
string
get_command_line
();
void
save_command_line
(
const
std
::
string
&
cli
);
void
add_file
(
const
std
::
string
&
section
,
const
IOFileInfo
&
file_info
);
void
set_modification_time
();
void
erase_all_files
();
void
erase_section_files
(
const
std
::
string
&
section
);
void
erase_section_files
(
const
std
::
string
&
section
,
bool
only_if_output
);
void
parse_file
();
void
write_to_disk
();
std
::
vector
<
std
::
string
>
get_section_names
(
const
std
::
string
&
name
);
bool
get_file
(
const
std
::
string
&
section
,
const
std
::
string
&
name
,
IOFileInfo
&
out
);
std
::
string
get_path
()
{
return
m_path
;
}
private
:
void
set_absolute_path
();
void
remove_file
(
const
std
::
string
&
node
,
std
::
size_t
id
);
void
remove_file
(
const
std
::
string
&
node
,
std
::
size_t
id
,
bool
only_if_output
);
std
::
string
m_filepath
{
""
};
std
::
string
m_path
{
""
};
YAML
::
Node
m_node
;
};
// ==== Call to implementation ==== //
AllIOFiles
::
AllIOFiles
(
std
::
string
filepath
,
AllIOFilesMode
mode
)
:
m_impl
(
utils
::
make_pimpl
<
AllIOFilesImpl
>
(
filepath
,
mode
))
{
}
AllIOFiles
::~
AllIOFiles
()
=
default
;
//! \brief Save the command line
void
AllIOFiles
::
save_command_line
(
int
argc
,
const
char
*
const
argv
[])
{
std
::
string
cmd
;
for
(
auto
id
=
0
;
id
<
argc
;
++
id
)
{
cmd
+=
std
::
string
(
argv
[
id
])
+
' '
;
}
if
(
not
cmd
.
empty
())
{
cmd
.
pop_back
();
}
m_impl
->
save_command_line
(
cmd
);
}
void
AllIOFiles
::
add_configuration_file
(
IOFileInfo
&&
file_info
)
{
m_impl
->
add_file
(
SPC_IO_S_INPUT
,
std
::
move
(
file_info
));
}
void
AllIOFiles
::
add_database
(
IOFileInfo
&&
file_info
)
{
m_impl
->
add_file
(
SPC_IO_S_DATABASE
,
std
::
move
(
file_info
));
}
void
AllIOFiles
::
add_solution
(
IOFileInfo
&&
file_info
)
{
m_impl
->
add_file
(
SPC_IO_S_SOLUTION
,
std
::
move
(
file_info
));
}
void
AllIOFiles
::
add_log_file
(
IOFileInfo
&&
file_info
)
{
m_impl
->
add_file
(
SPC_IO_S_LOGS
,
std
::
move
(
file_info
));
}
//! \brief Return the creation time
std
::
time_t
AllIOFiles
::
get_creation_time
()
{
return
m_impl
->
get_creation_time
();
}
//! \brief Return the last modification time
std
::
time_t
AllIOFiles
::
get_last_modification_time
()
{
return
m_impl
->
get_last_modification_time
();
}
//! \brief Return the command line
std
::
string
AllIOFiles
::
get_command_line
()
{
return
m_impl
->
get_command_line
();
}
std
::
vector
<
std
::
string
>
AllIOFiles
::
get_configuration_file_names
()
{
return
m_impl
->
get_section_names
(
SPC_IO_S_INPUT
);
}
bool
AllIOFiles
::
get_configuration_file
(
const
std
::
string
&
name
,
IOFileInfo
&
out
)
{
return
m_impl
->
get_file
(
SPC_IO_S_INPUT
,
name
,
out
);
}
std
::
vector
<
std
::
string
>
AllIOFiles
::
get_database_names
()
{
return
m_impl
->
get_section_names
(
SPC_IO_S_DATABASE
);
}
bool
AllIOFiles
::
get_database
(
const
std
::
string
&
name
,
IOFileInfo
&
out
)
{
return
m_impl
->
get_file
(
SPC_IO_S_DATABASE
,
name
,
out
);
}
std
::
vector
<
std
::
string
>
AllIOFiles
::
get_solution_names
()
{
return
m_impl
->
get_section_names
(
SPC_IO_S_SOLUTION
);
}
bool
AllIOFiles
::
get_solution
(
const
std
::
string
&
name
,
IOFileInfo
&
out
)
{
return
m_impl
->
get_file
(
SPC_IO_S_SOLUTION
,
name
,
out
);
}
std
::
vector
<
std
::
string
>
AllIOFiles
::
get_log_file_names
()
{
return
m_impl
->
get_section_names
(
SPC_IO_S_LOGS
);
}
bool
AllIOFiles
::
get_log_file
(
const
std
::
string
&
name
,
IOFileInfo
&
out
)
{
return
m_impl
->
get_file
(
SPC_IO_S_LOGS
,
name
,
out
);
}
void
AllIOFiles
::
clean_output_files
()
{
return
m_impl
->
erase_all_files
();
}
void
AllIOFiles
::
sync
()
{
m_impl
->
write_to_disk
();
}
std
::
string
AllIOFiles
::
get_working_dir
()
{
return
m_impl
->
get_path
();
}
// ==== Implementation ==== //
//! \brief Convert an IO type to a string
std
::
string
io_type_to_str
(
const
IOFileType
&
rhs
)
{
std
::
string
ret
;
switch
(
rhs
)
{
case
IOFileType
::
Input:
ret
=
SPC_IO_V_INPUT
;
break
;
case
IOFileType
::
Output:
ret
=
SPC_IO_V_OUTPUT
;
break
;
case
IOFileType
::
Input_Output:
ret
=
SPC_IO_V_IN_OUT_PUT
;
break
;
default
:
ERROR_THROW
(
"Invalid file type (IOFileType) when converting to string"
);
}
return
ret
;
}
//! \brief Convert a string to an IO type
IOFileType
str_to_io_type
(
const
std
::
string
&
rhs
)
{
IOFileType
type
;
if
(
rhs
==
SPC_IO_V_INPUT
)
{
type
=
IOFileType
::
Input
;
}
else
if
(
rhs
==
SPC_IO_V_OUTPUT
)
{
type
=
IOFileType
::
Output
;
}
else
if
(
rhs
==
SPC_IO_V_IN_OUT_PUT
)
{
type
=
IOFileType
::
Input_Output
;
}
else
{
ERROR_THROW
(
"Invalid file type '"
+
rhs
+
"' when converting to IOFileType"
);
}
return
type
;
}
}
// end namespace io
}
// end namespace specmicp
// YAML conversion
namespace
YAML
{
template
<>
struct
convert
<
specmicp
::
io
::
IOFileInfo
>
{
static
Node
encode
(
const
specmicp
::
io
::
IOFileInfo
&
rhs
)
{
Node
node
;
node
[
SPC_IO_A_NAME
]
=
rhs
.
name
;
node
[
SPC_IO_A_PATH
]
=
rhs
.
filepath
;
node
[
SPC_IO_A_TYPE
]
=
io_type_to_str
(
rhs
.
type
);
if
(
not
rhs
.
comment
.
empty
())
{
node
[
SPC_IO_A_COMMENT
]
=
rhs
.
comment
;
}
return
node
;
}
static
bool
decode
(
const
Node
&
node
,
specmicp
::
io
::
IOFileInfo
&
rhs
)
{
if
(
(
not
node
.
IsMap
())
or
(
not
node
[
SPC_IO_A_NAME
])
or
(
not
node
[
SPC_IO_A_PATH
])
or
(
not
node
[
SPC_IO_A_TYPE
]))
{
return
false
;
}
specmicp
::
io
::
IOFileType
type
=
specmicp
::
io
::
str_to_io_type
(
node
[
SPC_IO_A_TYPE
].
as
<
std
::
string
>
());
if
(
node
[
SPC_IO_A_COMMENT
])
{
rhs
=
specmicp
::
io
::
IOFileInfo
(
node
[
SPC_IO_A_NAME
].
as
<
std
::
string
>
(),
node
[
SPC_IO_A_PATH
].
as
<
std
::
string
>
(),
node
[
SPC_IO_A_COMMENT
].
as
<
std
::
string
>
(),
type
);
}
else
{
rhs
=
specmicp
::
io
::
IOFileInfo
(
node
[
SPC_IO_A_NAME
].
as
<
std
::
string
>
(),
node
[
SPC_IO_A_PATH
].
as
<
std
::
string
>
(),
type
);
}
return
true
;
}
};
}
namespace
specmicp
{
namespace
io
{
AllIOFiles
::
AllIOFilesImpl
::
AllIOFilesImpl
(
std
::
string
filepath
,
AllIOFilesMode
mode
)
{
auto
path_exists
=
utils
::
path_exists
(
filepath
);
m_filepath
=
filepath
;
if
(
path_exists
)
{
if
(
not
utils
::
is_file
(
filepath
))
{
ERROR_THROW
(
"IOError : "
+
filepath
+
" is not a file."
);
}
if
(
mode
==
AllIOFilesMode
::
ErrorIfExist
)
{
ERROR_THROW
(
"IOError : "
+
filepath
+
" already exists"
);
}
else
if
(
mode
==
AllIOFilesMode
::
Write
)
{
auto
other
=
AllIOFilesImpl
(
filepath
,
AllIOFilesMode
::
Read
);
other
.
erase_all_files
();
}
else
if
(
mode
==
AllIOFilesMode
::
Read
)
{
parse_file
();
}
}
if
(
(
mode
==
AllIOFilesMode
::
ErrorIfExist
)
or
(
mode
==
AllIOFilesMode
::
Write
)
)
{
m_node
[
SPC_IO_A_CREATION
]
=
dateandtime
::
now
();
set_modification_time
();
}
set_absolute_path
();
}
void
AllIOFiles
::
AllIOFilesImpl
::
add_file
(
const
std
::
string
&
section
,
const
IOFileInfo
&
file_info
)
{
m_node
[
section
].
push_back
(
YAML
::
Node
(
file_info
));
set_modification_time
();
}
void
AllIOFiles
::
AllIOFilesImpl
::
set_absolute_path
()
{
auto
splitted
=
utils
::
split_filepath
(
m_filepath
);
auto
&
dir
=
splitted
[
0
];
if
(
not
dir
.
empty
())
{
if
(
not
utils
::
is_path_absolute
(
dir
))
{
std
::
string
error
;
auto
tmp
=
utils
::
relative_to_absolute
(
dir
,
error
);
if
(
not
error
.
empty
())
{
ERROR_THROW
(
error
);
}
m_path
=
tmp
;
}
else
{
m_path
=
dir
;
}
}
else
{
m_path
=
utils
::
get_current_directory
();
}
}
void
AllIOFiles
::
AllIOFilesImpl
::
parse_file
()
{
m_node
=
parse_yaml_file
(
m_filepath
);
}
void
AllIOFiles
::
AllIOFilesImpl
::
erase_all_files
()
{
erase_section_files
(
SPC_IO_S_LOGS
);
erase_section_files
(
SPC_IO_S_SOLUTION
);
// Do not erase db if input
erase_section_files
(
SPC_IO_S_DATABASE
,
true
);
// DO not erase input !
erase_section_files
(
SPC_IO_S_INPUT
,
true
);
utils
::
remove_file
(
m_filepath
);
}
void
AllIOFiles
::
AllIOFilesImpl
::
erase_section_files
(
const
std
::
string
&
section
)
{
for
(
std
::
size_t
id
=
0
;
id
<
m_node
[
section
].
size
();
++
id
)
{
remove_file
(
section
,
id
);
}
}
void
AllIOFiles
::
AllIOFilesImpl
::
erase_section_files
(
const
std
::
string
&
section
,
bool
only_if_output
)
{
for
(
std
::
size_t
id
=
0
;
id
<
m_node
[
section
].
size
();
++
id
)
{
remove_file
(
section
,
id
,
only_if_output
);
}
}
void
AllIOFiles
::
AllIOFilesImpl
::
remove_file
(
const
std
::
string
&
section
,
std
::
size_t
id
)
{
auto
path
=
m_node
[
section
][
id
][
SPC_IO_A_PATH
].
as
<
std
::
string
>
();
if
(
not
utils
::
is_path_absolute
(
path
))
{
path
=
utils
::
complete_path
(
m_path
,
path
);
}
DEBUG
<<
"Removing : "
<<
path
;
utils
::
remove_file
(
path
);
m_node
[
section
].
remove
(
id
);
set_modification_time
();
}
void
AllIOFiles
::
AllIOFilesImpl
::
remove_file
(
const
std
::
string
&
section
,
std
::
size_t
id
,
bool
only_if_output
)
{
IOFileInfo
info
=
m_node
[
section
][
id
].
as
<
IOFileInfo
>
();
if
(
info
.
type
!=
IOFileType
::
Output
)
{
return
;
}
auto
path
=
info
.
filepath
;
if
(
not
utils
::
is_path_absolute
(
path
))
{
path
=
utils
::
complete_path
(
m_path
,
path
);
}
DEBUG
<<
"Removing : "
<<
path
;
utils
::
remove_file
(
path
);
m_node
[
section
].
remove
(
id
);
set_modification_time
();
}
void
AllIOFiles
::
AllIOFilesImpl
::
save_command_line
(
const
std
::
string
&
cli
)
{
m_node
[
SPC_IO_A_CLI
]
=
cli
;
set_modification_time
();
}
void
AllIOFiles
::
AllIOFilesImpl
::
set_modification_time
()
{
m_node
[
SPC_IO_A_MODIFICATION
]
=
dateandtime
::
now
();
}
void
AllIOFiles
::
AllIOFilesImpl
::
write_to_disk
()
{
YAML
::
Emitter
yaml_emitter
;
yaml_emitter
<<
m_node
;
DEBUG
<<
"Save AllIOFile to "
<<
m_filepath
<<
" - "
<<
utils
::
get_current_directory
();
DEBUG
<<
"YAML emitter size : "
<<
yaml_emitter
.
size
();
DEBUG
<<
"Before emitter : "
<<
m_node
[
SPC_IO_A_CLI
];
save_yaml
(
m_filepath
,
yaml_emitter
);
}
std
::
time_t
AllIOFiles
::
AllIOFilesImpl
::
get_creation_time
()
{
return
dateandtime
::
from_text
(
m_node
[
SPC_IO_A_CREATION
].
as
<
std
::
string
>
());
}
std
::
time_t
AllIOFiles
::
AllIOFilesImpl
::
get_last_modification_time
()
{
return
dateandtime
::
from_text
(
m_node
[
SPC_IO_A_MODIFICATION
].
as
<
std
::
string
>
());
}
std
::
string
AllIOFiles
::
AllIOFilesImpl
::
get_command_line
()
{
return
m_node
[
SPC_IO_A_CLI
].
as
<
std
::
string
>
();
}
std
::
vector
<
std
::
string
>
AllIOFiles
::
AllIOFilesImpl
::
get_section_names
(
const
std
::
string
&
section
)
{
const
auto
sec_node
=
m_node
[
section
];
std
::
vector
<
std
::
string
>
names
;
names
.
reserve
(
sec_node
.
size
());
for
(
const
auto
&
node:
sec_node
)
{
names
.
push_back
(
node
[
SPC_IO_A_NAME
].
as
<
std
::
string
>
());
}
return
names
;
}
bool
AllIOFiles
::
AllIOFilesImpl
::
get_file
(
const
std
::
string
&
section
,
const
std
::
string
&
name
,
IOFileInfo
&
out
)
{
const
YAML
::
Node
sec_node
=
m_node
[
section
];
for
(
const
auto
&
node:
sec_node
)
{
if
(
node
[
SPC_IO_A_NAME
]
and
node
[
SPC_IO_A_NAME
].
as
<
std
::
string
>
()
==
name
)
{
out
=
node
.
as
<
IOFileInfo
>
();
return
true
;
}
}
return
false
;
}
}
// end namespace io
}
// end namespace specmicp
Event Timeline
Log In to Comment