Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
dCache
cta
Commits
871796a1
Commit
871796a1
authored
Sep 27, 2018
by
Eric Cano
Browse files
Added a range iteratable generator.
parent
96f3b898
Changes
3
Hide whitespace changes
Inline
Side-by-side
common/CMakeLists.txt
View file @
871796a1
...
...
@@ -184,7 +184,8 @@ set (COMMON_UNIT_TESTS_LIB_SRC_FILES
utils/RegexTest.cpp
utils/UtilsTest.cpp
UserIdentityTest.cpp
optionalTest.cpp
)
optionalTest.cpp
rangeTest.cpp
)
add_library
(
ctacommonunittests SHARED
${
COMMON_UNIT_TESTS_LIB_SRC_FILES
}
)
...
...
common/range.hpp
0 → 100644
View file @
871796a1
/*
* The CERN Tape Archive (CTA) project
* Copyright (C) 2015 CERN
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include
<limits>
#include
"common/exception/Exception.hpp"
namespace
cta
{
template
<
typename
T
>
class
range
:
public
std
::
initializer_list
<
T
>
{
public:
range
(
T
begin
,
T
end
,
T
step
=
1
)
:
m_begin
(
begin
),
m_end
(
end
),
m_step
(
step
)
{}
class
iterator
{
private:
friend
range
;
enum
class
direction
:
bool
{
forward
,
backward
};
iterator
(
T
begin
,
T
end
,
T
step
,
iterator
::
direction
dir
)
:
m_val
(
begin
),
m_limit
(
end
),
m_step
(
step
),
m_dir
(
dir
)
{}
public:
CTA_GENERATE_EXCEPTION_CLASS
(
DereferencingPastEnd
);
T
operator
*
()
{
if
(
m_val
==
m_limit
)
throw
DereferencingPastEnd
(
"In range::operator*(): dereferencing out of bounds"
);
return
m_val
;
}
iterator
&
operator
++
()
{
doInc
();
return
*
this
;
}
iterator
operator
++
(
int
)
{
iterator
ret
(
*
this
);
doInc
();
return
ret
;
}
void
doInc
()
{
switch
(
m_dir
)
{
// Increment/decrement variable, preventing over/underflow, and overshooting the limit.
case
direction
::
forward
:
// Prevent overflow
if
(
m_step
>
std
::
numeric_limits
<
T
>::
max
()
-
m_val
)
{
m_val
=
m_limit
;
}
else
{
m_val
+=
m_step
;
// Prevent overshoot.
if
(
m_val
>
m_limit
)
m_val
=
m_limit
;
}
break
;
case
direction
::
backward
:
// Prevent underflow
if
(
m_step
>
m_val
-
std
::
numeric_limits
<
T
>::
max
()
)
{
m_val
=
m_limit
;
}
else
{
m_val
-=
m_step
;
if
(
m_val
<
m_limit
)
m_val
=
m_limit
;
}
break
;
}
}
bool
operator
==
(
const
iterator
&
other
)
{
checkIteratorsComparable
(
other
);
return
m_val
==
other
.
m_val
;
}
bool
operator
!=
(
const
iterator
&
other
)
{
checkIteratorsComparable
(
other
);
return
m_val
!=
other
.
m_val
;
}
CTA_GENERATE_EXCEPTION_CLASS
(
NonComparableIterators
);
private:
void
checkIteratorsComparable
(
const
iterator
&
other
)
const
{
if
(
m_limit
!=
other
.
m_limit
||
m_step
!=
other
.
m_step
||
m_dir
!=
other
.
m_dir
)
throw
NonComparableIterators
(
"In range::checkIteratorsComparable(): comparing iterators from different ranges."
);
}
T
m_val
;
const
T
m_limit
,
m_step
;
direction
m_dir
;
};
iterator
cbegin
()
const
{
return
iterator
(
m_begin
,
m_end
,
m_step
,
m_begin
<=
m_end
?
iterator
::
direction
::
forward
:
iterator
::
direction
::
backward
);
}
iterator
cend
()
const
{
return
iterator
(
m_end
,
m_end
,
m_step
,
m_begin
<=
m_end
?
iterator
::
direction
::
forward
:
iterator
::
direction
::
backward
);
}
iterator
begin
()
const
{
return
cbegin
();
}
iterator
end
()
const
{
return
cend
();
}
private:
const
T
m_begin
;
const
T
m_end
;
const
T
m_step
;
};
}
// namesapce cta
common/rangeTest.cpp
0 → 100644
View file @
871796a1
/*
* The CERN Tape Archive (CTA) project
* Copyright (C) 2015 CERN
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include
"range.hpp"
#include
<list>
#include
<gtest/gtest.h>
namespace
unitTests
{
TEST
(
cta_rangeTest
,
basic
)
{
using
namespace
cta
;
std
::
list
<
size_t
>
l
;
// Test forward
for
(
const
auto
&
i
:
range
<
size_t
>
(
0
,
4
))
l
.
emplace_back
(
i
);
ASSERT_EQ
(
std
::
list
<
size_t
>
({
0
,
1
,
2
,
3
}),
l
);
l
.
clear
();
// Test forward with step.
for
(
const
auto
&
i
:
range
<
size_t
>
(
0
,
10
,
3
))
l
.
emplace_back
(
i
);
ASSERT_EQ
(
std
::
list
<
size_t
>
({
0
,
3
,
6
,
9
}),
l
);
l
.
clear
();
// Test forward overflow
const
auto
max
=
std
::
numeric_limits
<
size_t
>::
max
();
for
(
const
auto
&
i
:
range
<
size_t
>
(
max
-
10
,
max
,
3
))
l
.
emplace_back
(
i
);
ASSERT_EQ
(
std
::
list
<
size_t
>
({
max
-
10
,
max
-
7
,
max
-
4
,
max
-
1
}),
l
);
l
.
clear
();
// Test backwards
for
(
const
auto
&
i
:
range
<
size_t
>
(
10
,
5
))
l
.
emplace_back
(
i
);
ASSERT_EQ
(
std
::
list
<
size_t
>
({
10
,
9
,
8
,
7
,
6
}),
l
);
l
.
clear
();
// Test backwards with step and underflow.
for
(
const
auto
&
i
:
range
<
size_t
>
(
10
,
0
,
3
))
l
.
emplace_back
(
i
);
ASSERT_EQ
(
std
::
list
<
size_t
>
({
10
,
7
,
4
,
1
}),
l
);
}
}
\ No newline at end of file
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment