Skip to content

Commit 34ec7ab

Browse files
committed
added function cif::Column::erase()
requested in #251
1 parent 05e72c2 commit 34ec7ab

File tree

4 files changed

+39
-1
lines changed

4 files changed

+39
-1
lines changed

docs/cif.rst

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -940,7 +940,7 @@ The C++ signature of ``find_values`` is::
940940
// Returns underlying Item (which contains either Pair or Loop).
941941
Item* item();
942942

943-
// Returns pointer to the DOM structure containing the whole table.
943+
// If it's in Loop, returns pointer to Loop; otherwise, nullptr.
944944
Loop* get_loop() const;
945945

946946
// Get raw value (no bounds checking).
@@ -952,6 +952,9 @@ The C++ signature of ``find_values`` is::
952952
// Short-cut for cif::as_string(column.at(n)).
953953
std::string str(int n) const;
954954

955+
// Erases item for name-value pair; removes column for Loop
956+
void erase();
957+
955958
``Column`` also provides support for C++11 range-based ``for``::
956959

957960
// mmCIF _chem_comp_atom is usually a table, but not always
@@ -1011,6 +1014,16 @@ to this ``Loop`` in the DOM. Otherwise it returns ``None``.
10111014
>>> column.get_loop()
10121015
<gemmi.cif.Loop 12 x 7>
10131016

1017+
``erase()`` removes the column from a loop, if this column is in a loop;
1018+
if it's a tag-value pair it erases the containing item.
1019+
1020+
.. doctest::
1021+
1022+
>>> loop = column.get_loop()
1023+
>>> column.erase()
1024+
>>> loop # one column less
1025+
<gemmi.cif.Loop 12 x 6>
1026+
10141027
Table
10151028
=====
10161029

include/gemmi/cifdoc.hpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,11 @@ struct Loop {
199199
int n = find_tag(column_name);
200200
if (n == -1)
201201
fail("remove_column(): tag not found: " + column_name);
202+
remove_column_at(n);
203+
}
204+
205+
/// \pre: n < tags.size()
206+
void remove_column_at(size_t n) {
202207
tags.erase(tags.begin() + n);
203208
vector_remove_column(values, tags.size(), n);
204209
}
@@ -264,6 +269,8 @@ class Column {
264269
Item* item() { return item_; }
265270
size_t col() const { return col_; }
266271

272+
void erase();
273+
267274
private:
268275
Item* item_;
269276
size_t col_; // for loop this is a column index in item_->loop
@@ -657,6 +664,13 @@ inline std::string* Column::get_tag() {
657664
return &item_->pair[0];
658665
}
659666

667+
inline void Column::erase() {
668+
if (Loop* loop = get_loop())
669+
loop->remove_column_at(col_);
670+
else if (item_)
671+
item_->erase();
672+
}
673+
660674
inline Loop* Column::get_loop() const {
661675
return item_ && item_->type == ItemType::Loop ? &item_->loop : nullptr;
662676
}

python/cif.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ void add_cif(py::module& cif) {
370370
self.at(idx) = value;
371371
})
372372
.def("str", &Column::str, py::arg("index"))
373+
.def("erase", &Column::erase)
373374
.def("__repr__", [](const Column &self) {
374375
std::string s = "<gemmi.cif.Column ";
375376
if (const std::string* tag = self.get_tag())

tests/test_cif.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,16 @@ def test_case_sensitivity(self):
350350
self.assertEqual(block.get_index('_lBBB'), 5)
351351
self.assertEqual(block.find_pair('_Three'), ('_thrEE', '3'))
352352

353+
values.erase()
354+
block.find_values('_two').erase()
355+
block.find_values('_nonloop_b').erase()
356+
expected = """\
357+
data_test
358+
_One 1 _thrEE 3
359+
_NonLoop_a alpha
360+
loop_ _lbBb _ln B 1 D 2"""
361+
self.assertEqual(block.as_string().split(), expected.split())
362+
353363
class TestQuote(unittest.TestCase):
354364
def test_quote(self):
355365
self.assertEqual(cif.quote('a.b-c'), 'a.b-c')

0 commit comments

Comments
 (0)