Commit 58fcdd87 authored by Kirill Smelkov's avatar Kirill Smelkov

cxx: Correct dict interface

Package cxx was added in 9785f2d3 (cxx: New package), but the interface
that cxx:dict provided turned out to be not optimal:

    dict.get  was returning (v, ok), and
    dict.pop  ----//---

Correct dict.get and dict.pop to return just value, and, similarly to
channels API, provide additional dict.get_ and dict.pop_ - extended
versions that also return ok:

    dict.get(k)  -> v
    dict.pop(k)  -> v
    dict.get_(k) -> (v, ok)
    dict.pop_(k) -> (v, ok)

This time add tests.
parent dbd051f1
/_context.cpp /_context.cpp
/_cxx_test.cpp
/_errors_test.cpp /_errors_test.cpp
/_fmt_test.cpp /_fmt_test.cpp
/_golang.cpp /_golang.cpp
......
# -*- coding: utf-8 -*-
# cython: language_level=2
# distutils: language=c++
#
# Copyright (C) 2020 Nexedi SA and Contributors.
# Kirill Smelkov <kirr@nexedi.com>
#
# This program is free software: you can Use, Study, Modify and Redistribute
# it under the terms of the GNU General Public License version 3, or (at your
# option) any later version, as published by the Free Software Foundation.
#
# You can also Link and Combine this program with other software covered by
# the terms of any of the Free Software licenses or any of the Open Source
# Initiative approved licenses and Convey the resulting work. Corresponding
# source of such a combination shall include the source code for all other
# software used.
#
# This program is distributed WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# See COPYING file for full licensing terms.
# See https://www.nexedi.com/licensing for rationale and options.
from __future__ import print_function, absolute_import
from golang cimport topyexc
# cxx_test.cpp
cdef extern from * nogil:
"""
extern void _test_cxx_dict();
extern void _test_cxx_set();
"""
void _test_cxx_dict() except +topyexc
void _test_cxx_set() except +topyexc
def test_cxx_dict():
with nogil:
_test_cxx_dict()
def test_cxx_set():
with nogil:
_test_cxx_set()
#ifndef _NXD_LIBGOLANG_CXX_H #ifndef _NXD_LIBGOLANG_CXX_H
#define _NXD_LIBGOLANG_CXX_H #define _NXD_LIBGOLANG_CXX_H
// Copyright (C) 2019 Nexedi SA and Contributors. // Copyright (C) 2019-2020 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com> // Kirill Smelkov <kirr@nexedi.com>
// //
// This program is free software: you can Use, Study, Modify and Redistribute // This program is free software: you can Use, Study, Modify and Redistribute
...@@ -31,6 +31,8 @@ namespace golang { ...@@ -31,6 +31,8 @@ namespace golang {
namespace cxx { namespace cxx {
using std::tuple; using std::tuple;
using std::tie;
using std::make_tuple;
// dict wraps unordered_map into ergonomic interface. // dict wraps unordered_map into ergonomic interface.
template<typename Key, typename Value> template<typename Key, typename Value>
...@@ -41,8 +43,14 @@ struct dict : std::unordered_map<Key, Value> { ...@@ -41,8 +43,14 @@ struct dict : std::unordered_map<Key, Value> {
return d.find(k) != d.end(); return d.find(k) != d.end();
} }
// get implements `d[k] -> (v, ok)`. // get implements `d[k] -> v`.
tuple<Value, bool> get(const Key &k) const { Value get(const Key &k) const {
Value v; bool _; tie(v, _) = get_(k);
return v;
}
// get_ implements `d[k] -> (v, ok)`.
tuple<Value, bool> get_(const Key &k) const {
const dict &d = *this; const dict &d = *this;
auto _ = d.find(k); auto _ = d.find(k);
if (_ == d.end()) if (_ == d.end())
...@@ -50,8 +58,14 @@ struct dict : std::unordered_map<Key, Value> { ...@@ -50,8 +58,14 @@ struct dict : std::unordered_map<Key, Value> {
return make_tuple(_->second, true); return make_tuple(_->second, true);
} }
// pop implements `d[k] -> (v, ok); del d[k]`. // pop implements `d[k] -> v; del d[k]`.
tuple<Value, bool> pop(const Key &k) { Value pop(const Key &k) {
Value v; bool _; tie(v, _) = pop_(k);
return v;
}
// pop_ implements `d[k] -> (v, ok); del d[k]`.
tuple<Value, bool> pop_(const Key &k) {
dict &d = *this; dict &d = *this;
auto _ = d.find(k); auto _ = d.find(k);
if (_ == d.end()) if (_ == d.end())
......
# cython: language_level=2 # cython: language_level=2
# Copyright (C) 2019 Nexedi SA and Contributors. # Copyright (C) 2019-2020 Nexedi SA and Contributors.
# Kirill Smelkov <kirr@nexedi.com> # Kirill Smelkov <kirr@nexedi.com>
# #
# This program is free software: you can Use, Study, Modify and Redistribute # This program is free software: you can Use, Study, Modify and Redistribute
...@@ -25,8 +25,8 @@ cimport libcpp.unordered_set ...@@ -25,8 +25,8 @@ cimport libcpp.unordered_set
cdef extern from "<golang/cxx.h>" namespace "golang::cxx" nogil: cdef extern from "<golang/cxx.h>" namespace "golang::cxx" nogil:
cppclass dict[Key, Value] (libcpp.unordered_map.unordered_map[Key, Value]): cppclass dict[Key, Value] (libcpp.unordered_map.unordered_map[Key, Value]):
bint has(Key k) const bint has(Key k) const
# TODO get # TODO get/get_
# TODO pop # TODO pop/pop_
cppclass set[Key] (libcpp.unordered_set.unordered_set[Key]): cppclass set[Key] (libcpp.unordered_set.unordered_set[Key]):
bint has(Key k) const bint has(Key k) const
// Copyright (C) 2020 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com>
//
// This program is free software: you can Use, Study, Modify and Redistribute
// it under the terms of the GNU General Public License version 3, or (at your
// option) any later version, as published by the Free Software Foundation.
//
// You can also Link and Combine this program with other software covered by
// the terms of any of the Free Software licenses or any of the Open Source
// Initiative approved licenses and Convey the resulting work. Corresponding
// source of such a combination shall include the source code for all other
// software used.
//
// This program is distributed WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
// See COPYING file for full licensing terms.
// See https://www.nexedi.com/licensing for rationale and options.
#include "golang/cxx.h"
#include "golang/_testing.h"
using namespace golang;
using std::tie;
void _test_cxx_dict() {
cxx::dict<string, int> d;
d["abc"] = 1;
d["def"] = 2;
// has
ASSERT(d.has("abc"));
ASSERT(d.has("def"));
ASSERT(!d.has("zzz"));
// get
ASSERT_EQ(d.get("abc"), 1);
ASSERT_EQ(d.get("def"), 2);
ASSERT_EQ(d.get("zzz"), 0);
int v; bool ok;
// get_
tie(v, ok) = d.get_("abc");
ASSERT_EQ(v, 1); ASSERT_EQ(ok, true);
tie(v, ok) = d.get_("def");
ASSERT_EQ(v, 2); ASSERT_EQ(ok, true);
tie(v, ok) = d.get_("zzz");
ASSERT_EQ(v, 0); ASSERT_EQ(ok, false);
// pop / pop_
ASSERT_EQ(d.pop("zzz"), 0);
tie(v, ok) = d.pop_("zzz");
ASSERT_EQ(v, 0); ASSERT_EQ(ok, false);
ASSERT(d.has("def"));
ASSERT_EQ(d.pop("def"), 2);
ASSERT(!d.has("def"));
ASSERT_EQ(d.pop("def"), 0);
ASSERT(!d.has("def"));
ASSERT(d.has("abc"));
tie(v, ok) = d.pop_("abc");
ASSERT_EQ(v, 1); ASSERT_EQ(ok, true);
ASSERT(!d.has("abc"));
tie(v, ok) = d.pop_("abc");
ASSERT_EQ(v, 0); ASSERT_EQ(ok, false);
}
void _test_cxx_set() {
cxx::set<string> s;
s.insert("abc");
s.insert("def");
// has
ASSERT(s.has("abc"));
ASSERT(s.has("def"));
ASSERT(!s.has("zzz"));
// has after erase
s.erase("zzz");
ASSERT(s.has("abc"));
ASSERT(s.has("def"));
ASSERT(!s.has("zzz"));
s.erase("def");
ASSERT(s.has("abc"));
ASSERT(!s.has("def"));
ASSERT(!s.has("zzz"));
s.erase("abc");
ASSERT(!s.has("abc"));
ASSERT(!s.has("def"));
ASSERT(!s.has("zzz"));
}
# -*- coding: utf-8 -*-
# Copyright (C) 2020 Nexedi SA and Contributors.
# Kirill Smelkov <kirr@nexedi.com>
#
# This program is free software: you can Use, Study, Modify and Redistribute
# it under the terms of the GNU General Public License version 3, or (at your
# option) any later version, as published by the Free Software Foundation.
#
# You can also Link and Combine this program with other software covered by
# the terms of any of the Free Software licenses or any of the Open Source
# Initiative approved licenses and Convey the resulting work. Corresponding
# source of such a combination shall include the source code for all other
# software used.
#
# This program is distributed WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# See COPYING file for full licensing terms.
# See https://www.nexedi.com/licensing for rationale and options.
from __future__ import print_function, absolute_import
from golang.golang_test import import_pyx_tests
import_pyx_tests("golang._cxx_test")
...@@ -251,6 +251,10 @@ setup( ...@@ -251,6 +251,10 @@ setup(
Ext('golang._context', Ext('golang._context',
['golang/_context.pyx']), ['golang/_context.pyx']),
Ext('golang._cxx_test',
['golang/_cxx_test.pyx',
'golang/cxx_test.cpp']),
Ext('golang._errors_test', Ext('golang._errors_test',
['golang/_errors_test.pyx', ['golang/_errors_test.pyx',
'golang/errors_test.cpp']), 'golang/errors_test.cpp']),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment