Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F73789434
string_algorithms.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
Wed, Jul 24, 11:37
Size
8 KB
Mime Type
text/x-c++
Expires
Fri, Jul 26, 11:37 (2 d)
Engine
blob
Format
Raw Data
Handle
19269715
Attached To
rSPECMICP SpecMiCP / ReactMiCP
string_algorithms.cpp
View Options
/* =============================================================================
Copyright (c) 2014 - 2016
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 "string_algorithms.hpp"
#include <algorithm>
namespace
specmicp
{
namespace
utils
{
//! \brief Split a string
std
::
vector
<
std
::
string
>
split
(
const
std
::
string
&
to_split
,
char
separator
)
{
std
::
vector
<
std
::
string
>
splitted
;
auto
nb_elem
=
std
::
count
(
to_split
.
begin
(),
to_split
.
end
(),
separator
);
splitted
.
reserve
(
nb_elem
+
1
);
auto
start
=
to_split
.
begin
();
for
(
auto
current
=
to_split
.
cbegin
();
current
!=
to_split
.
cend
();
++
current
)
{
if
(
*
current
==
separator
)
{
splitted
.
emplace_back
(
to_split
.
substr
(
start
-
to_split
.
cbegin
(),
current
-
start
));
start
=
current
+
1
;
}
}
// last value
if
(
start
<
to_split
.
cend
())
{
splitted
.
emplace_back
(
to_split
.
substr
(
start
-
to_split
.
cbegin
()));
}
return
splitted
;
}
std
::
string
strip
(
const
std
::
string
&
to_trim
)
{
auto
start
=
to_trim
.
begin
();
auto
end
=
to_trim
.
end
();
// at the beginning
auto
current
=
to_trim
.
begin
();
for
(;
current
!=
to_trim
.
cend
();
++
current
)
{
if
(
*
current
!=
' '
)
{
start
=
current
;
break
;
}
}
if
(
current
==
to_trim
.
cend
())
{
return
""
;}
// empty string
// at the end
for
(
auto
current
=
to_trim
.
cend
()
-
1
;
current
>=
to_trim
.
begin
();
--
current
)
{
if
(
*
current
!=
' '
)
{
end
=
++
current
;
break
;
}
}
return
to_trim
.
substr
(
start
-
to_trim
.
begin
(),
end
-
start
);
}
void
parse_one_term
(
std
::
vector
<
index_t
>&
numbers
,
const
std
::
string
&
term
);
std
::
vector
<
index_t
>
range_indices
(
const
std
::
string
&
range_str
)
{
std
::
vector
<
index_t
>
numbers
;
const
index_t
nb_sep
=
std
::
count
(
range_str
.
cbegin
(),
range_str
.
cend
(),
','
);
numbers
.
reserve
(
nb_sep
+
1
);
if
(
nb_sep
==
0
)
{
// if only one term
parse_one_term
(
numbers
,
range_str
);
}
else
{
const
std
::
vector
<
std
::
string
>
terms
=
split
(
range_str
,
','
);
for
(
const
auto
&
term:
terms
)
{
parse_one_term
(
numbers
,
term
);
}
}
// sort the indices
std
::
sort
(
numbers
.
begin
(),
numbers
.
end
());
return
numbers
;
}
void
parse_one_term
(
std
::
vector
<
index_t
>&
numbers
,
const
std
::
string
&
term
)
{
if
(
term
==
""
)
return
;
// check for empty terms
const
auto
to_anal
=
strip
(
term
);
const
auto
is_range
=
std
::
find
(
to_anal
.
cbegin
(),
to_anal
.
cend
(),
'-'
);
if
(
is_range
==
to_anal
.
cend
())
{
// if just a number
numbers
.
push_back
(
std
::
stol
(
to_anal
));
}
else
{
// if a range
const
std
::
string
first_str
=
to_anal
.
substr
(
0
,
is_range
-
to_anal
.
cbegin
());
const
std
::
string
last_str
=
to_anal
.
substr
(
is_range
-
to_anal
.
cbegin
()
+
1
);
const
index_t
first
=
std
::
stol
(
first_str
);
const
index_t
last
=
std
::
stol
(
last_str
);
for
(
auto
ind
=
first
;
ind
<=
last
;
++
ind
)
{
numbers
.
push_back
(
ind
);
}
}
}
template
<
typename
T
>
class
ExpressionParser
{
public
:
ExpressionParser
(
const
std
::
string
&
expr
,
const
std
::
unordered_map
<
std
::
string
,
T
>&
vars
)
:
complete_expr
(
expr
),
variables
(
vars
)
{
}
T
parse
()
{
return
parse_term
(
complete_expr
);}
T
parse_value
(
const
std
::
string
&
value
);
T
parse_factor
(
const
std
::
string
&
factor
);
T
parse_term
(
const
std
::
string
&
term
);
private
:
const
std
::
string
&
complete_expr
;
const
std
::
unordered_map
<
std
::
string
,
T
>&
variables
;
};
template
<>
scalar_t
ExpressionParser
<
scalar_t
>::
parse_value
(
const
std
::
string
&
expr
)
{
auto
trimmed_expr
=
strip
(
expr
);
if
(
trimmed_expr
==
""
)
{
throw
std
::
invalid_argument
(
"Error while parsing : "
+
complete_expr
);
}
scalar_t
val
=
std
::
nan
(
""
);
try
{
val
=
std
::
stod
(
trimmed_expr
);
}
catch
(
const
std
::
invalid_argument
&
e
)
{
auto
it
=
variables
.
find
(
trimmed_expr
);
if
(
it
==
variables
.
cend
())
{
throw
std
::
invalid_argument
(
"Unknown variable '"
+
trimmed_expr
+
"' in parsing of '"
+
complete_expr
+
"'."
);
}
val
=
it
->
second
;
}
return
val
;
}
template
<>
index_t
ExpressionParser
<
index_t
>::
parse_value
(
const
std
::
string
&
expr
)
{
auto
trimmed_expr
=
strip
(
expr
);
index_t
val
=
INT_MAX
;
try
{
val
=
std
::
stol
(
trimmed_expr
);
}
catch
(
const
std
::
invalid_argument
&
e
)
{
auto
it
=
variables
.
find
(
trimmed_expr
);
if
(
it
==
variables
.
cend
())
{
throw
std
::
invalid_argument
(
"Unknown variable '"
+
trimmed_expr
+
"' in parsing of '"
+
complete_expr
+
"'."
);
}
val
=
it
->
second
;
}
return
val
;
}
template
<
typename
T
>
T
ExpressionParser
<
T
>::
parse_factor
(
const
std
::
string
&
expr
)
{
auto
pred
=
[](
const
char
&
t
)
->
bool
{
return
((
t
==
'*'
)
or
(
t
==
'/'
));};
auto
it
=
std
::
find_if
(
expr
.
begin
(),
expr
.
end
(),
pred
);
if
(
it
==
expr
.
cend
())
{
return
parse_value
(
expr
);
}
auto
val1
=
parse_value
(
expr
.
substr
(
0
,
it
-
expr
.
cbegin
()));
auto
val2
=
parse_factor
(
expr
.
substr
((
it
-
expr
.
cbegin
())
+
1
));
if
(
*
it
==
'*'
)
{
return
val1
*
val2
;
}
else
{
return
val1
/
val2
;
}
return
0
;
}
template
<
typename
T
>
T
ExpressionParser
<
T
>::
parse_term
(
const
std
::
string
&
expr
)
{
auto
pred
=
[](
const
char
&
t
)
->
bool
{
return
((
t
==
'+'
)
or
(
t
==
'-'
));};
auto
it
=
std
::
find_if
(
expr
.
begin
(),
expr
.
end
(),
pred
);
if
(
it
==
expr
.
cend
())
{
return
parse_factor
(
expr
);
}
else
if
(
it
!=
expr
.
cbegin
())
{
auto
val1
=
parse_factor
(
expr
.
substr
(
0
,
it
-
expr
.
cbegin
()));
auto
val2
=
parse_factor
(
expr
.
substr
((
it
-
expr
.
cbegin
())
+
1
));
if
(
*
it
==
'+'
)
{
return
val1
+
val2
;
}
else
{
return
val1
-
val2
;
}
}
else
{
if
(
*
it
==
'-'
)
{
return
-
parse_term
(
expr
.
substr
(
1
));
}
else
{
return
parse_term
(
expr
.
substr
(
1
));
}
}
return
0
;
}
template
<>
scalar_t
parse_expression
(
const
std
::
string
&
expr
,
const
std
::
unordered_map
<
std
::
string
,
scalar_t
>&
variables
)
{
return
ExpressionParser
<
scalar_t
>
(
expr
,
variables
).
parse
();
}
template
<>
index_t
parse_expression
(
const
std
::
string
&
expr
,
const
std
::
unordered_map
<
std
::
string
,
index_t
>&
variables
)
{
return
ExpressionParser
<
index_t
>
(
expr
,
variables
).
parse
();
}
}
//end namespace utils
}
//end namespace specmicp
Event Timeline
Log In to Comment