forked from diffblue/cbmc
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathjar_file.cpp
129 lines (109 loc) · 3.19 KB
/
jar_file.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/*******************************************************************\
Module: Jar file reader
Author: Diffblue Ltd
\*******************************************************************/
#include "jar_file.h"
#include <algorithm>
#include <cctype>
#include <sstream>
void jar_filet::initialize_file_index()
{
const size_t file_count=m_zip_archive.get_num_files();
for(size_t index=0; index<file_count; index++)
m_name_to_index.emplace(m_zip_archive.get_filename(index), index);
}
/// This constructor creates a jar_file object whose contents
/// are extracted from a file with given name.
jar_filet::jar_filet(
const std::string &filename):
m_zip_archive(filename)
{
initialize_file_index();
}
/// This constructor creates a jar_file object whose contents
/// are extracted from a memory buffer (byte array) as opposed
/// to a jar file.
jar_filet::jar_filet(
const void *data,
size_t size):
m_zip_archive(data, size)
{
initialize_file_index();
}
// VS: No default move constructors or assigns
jar_filet::jar_filet(jar_filet &&other)
: m_zip_archive(std::move(other.m_zip_archive)),
m_name_to_index(std::move(other.m_name_to_index))
{
}
jar_filet &jar_filet::operator=(jar_filet &&other)
{
m_zip_archive=std::move(other.m_zip_archive);
m_name_to_index=std::move(other.m_name_to_index);
return *this;
}
std::optional<std::string> jar_filet::get_entry(const std::string &name)
{
const auto entry=m_name_to_index.find(name);
if(entry==m_name_to_index.end())
return {};
try
{
return m_zip_archive.extract(entry->second);
}
catch(const std::runtime_error &)
{
return {};
}
}
/// Wrapper for `std::isspace` from `cctype`
/// \param ch: the character to check
/// \return true if the parameter is considered to be a space in the current
/// locale, else false
static bool is_space(const char ch)
{
return std::isspace(ch) != 0;
}
/// Remove leading and trailing whitespace characters from string
/// \param begin: iterator to start search in string
/// \param end: iterator to end search in string
/// \return string truncated from begin to end and all whitespace removed at the
/// begin and end
static std::string trim(
const std::string::const_iterator begin,
const std::string::const_iterator end)
{
const auto out_begin=std::find_if_not(begin, end, is_space);
const auto out_end=std::find_if_not(
std::string::const_reverse_iterator(end),
std::string::const_reverse_iterator(out_begin),
is_space).base();
return { out_begin, out_end };
}
std::unordered_map<std::string, std::string> jar_filet::get_manifest()
{
const auto entry=get_entry("META-INF/MANIFEST.MF");
if(!entry.has_value())
return {};
std::unordered_map<std::string, std::string> out;
std::istringstream in(*entry);
std::string line;
while(std::getline(in, line))
{
const auto key_end=std::find(line.cbegin(), line.cend(), ':');
if(key_end!=line.cend())
{
out.emplace(
trim(line.cbegin(), key_end),
trim(std::next(key_end), line.cend()));
}
}
return out;
}
std::vector<std::string> jar_filet::filenames() const
{
std::vector<std::string> out;
for(const auto &pair : m_name_to_index)
out.emplace_back(pair.first);
return out;
}