Skip to content

Commit

Permalink
atlas_io is an adaptor library when eckit_codec is available
Browse files Browse the repository at this point in the history
  • Loading branch information
wdeconinck committed Nov 7, 2023
1 parent 5ea733a commit 20785f8
Show file tree
Hide file tree
Showing 10 changed files with 360 additions and 6 deletions.
18 changes: 16 additions & 2 deletions atlas_io/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,16 @@ ecbuild_debug( " eckit_FEATURES : [${eckit_FEATURES}]" )
################################################################################
# Features that can be enabled / disabled with -DENABLE_<FEATURE>

set( eckit_HAVE_ECKIT_CODEC 0 )
if( TARGET eckit_codec )
set( eckit_HAVE_ECKIT_CODEC 1 )
endif()

ecbuild_add_option( FEATURE ECKIT_CODEC
DEFAULT ON
DESCRIPTION "Use eckit::codec with adaptor"
CONDITION eckit_HAVE_ECKIT_CODEC )

################################################################################
# sources

Expand All @@ -47,8 +57,12 @@ else()
set( ATLAS_IO_LITTLE_ENDIAN 1 )
endif()


add_subdirectory( src )
if( HAVE_ECKIT_CODEC )
ecbuild_info("atlas_io is configured to be an adaptor library which delegates calls to eckit_codec")
add_subdirectory(eckit_codec_adaptor)
else()
add_subdirectory( src )
endif()
add_subdirectory( tests )

################################################################################
Expand Down
1 change: 1 addition & 0 deletions atlas_io/eckit_codec_adaptor/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
add_subdirectory(src)
2 changes: 2 additions & 0 deletions atlas_io/eckit_codec_adaptor/src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
add_subdirectory(atlas_io)

19 changes: 19 additions & 0 deletions atlas_io/eckit_codec_adaptor/src/atlas_io/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@

ecbuild_add_library( TARGET atlas_io

INSTALL_HEADERS ALL
HEADER_DESTINATION include/atlas_io
PUBLIC_LIBS eckit_codec
PUBLIC_INCLUDES
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/eckit_codec_adaptor/src>

SOURCES
atlas-io.h
Trace.cc
Trace.h
detail/BlackMagic.h
LINKER_LANGUAGE CXX
)

target_compile_features( atlas_io PUBLIC cxx_std_17 )

43 changes: 43 additions & 0 deletions atlas_io/eckit_codec_adaptor/src/atlas_io/Trace.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* (C) Copyright 2020 ECMWF.
*
* This software is licensed under the terms of the Apache Licence Version 2.0
* which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
* In applying this licence, ECMWF does not waive the privileges and immunities
* granted to it by virtue of its status as an intergovernmental organisation
* nor does it submit to any jurisdiction.
*/

#include "Trace.h"

#include "eckit/log/CodeLocation.h"

namespace atlas {
namespace io {

atlas::io::Trace::Trace(const eckit::CodeLocation& loc) {
for (size_t id = 0; id < TraceHookRegistry::size(); ++id) {
if (TraceHookRegistry::enabled(id)) {
hooks_.emplace_back(TraceHookRegistry::hook(id)(loc, loc.func()));
}
}
}

Trace::Trace(const eckit::CodeLocation& loc, const std::string& title) {
for (size_t id = 0; id < TraceHookRegistry::size(); ++id) {
if (TraceHookRegistry::enabled(id)) {
hooks_.emplace_back(TraceHookRegistry::hook(id)(loc, title));
}
}
}

Trace::Trace(const eckit::CodeLocation& loc, const std::string& title, const Labels& labels) {
for (size_t id = 0; id < TraceHookRegistry::size(); ++id) {
if (TraceHookRegistry::enabled(id)) {
hooks_.emplace_back(TraceHookRegistry::hook(id)(loc, title));
}
}
}

} // namespace io
} // namespace atlas
77 changes: 77 additions & 0 deletions atlas_io/eckit_codec_adaptor/src/atlas_io/Trace.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* (C) Copyright 2020 ECMWF.
*
* This software is licensed under the terms of the Apache Licence Version 2.0
* which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
* In applying this licence, ECMWF does not waive the privileges and immunities
* granted to it by virtue of its status as an intergovernmental organisation
* nor does it submit to any jurisdiction.
*/

#pragma once


#include <functional>
#include <memory>
#include <string>
#include <vector>
#include <limits>

namespace eckit {
class CodeLocation;
}

namespace atlas {
namespace io {

struct TraceHook {
TraceHook() = default;
virtual ~TraceHook() = default;
};

struct TraceHookRegistry {
using TraceHookBuilder = std::function<std::unique_ptr<TraceHook>(const eckit::CodeLocation&, const std::string&)>;
std::vector<TraceHookBuilder> hooks;
std::vector<int> enabled_;
static TraceHookRegistry& instance() {
static TraceHookRegistry instance;
return instance;
}
static size_t add(TraceHookBuilder&& hook) {
instance().hooks.emplace_back(hook);
instance().enabled_.emplace_back(true);
return instance().hooks.size() - 1;
}
static size_t add(const TraceHookBuilder& hook) {
instance().hooks.emplace_back(hook);
instance().enabled_.emplace_back(true);
return instance().hooks.size() - 1;
}
static void enable(size_t id) { instance().enabled_[id] = true; }
static void disable(size_t id) { instance().enabled_[id] = false; }
static bool enabled(size_t id) { return instance().enabled_[id]; }
static size_t size() { return instance().hooks.size(); }
static TraceHookBuilder& hook(size_t id) { return instance().hooks[id]; }
static size_t invalidId() { return std::numeric_limits<size_t>::max(); }

private:
TraceHookRegistry() = default;
};

struct Trace {
using Labels = std::vector<std::string>;
Trace(const eckit::CodeLocation& loc);
Trace(const eckit::CodeLocation& loc, const std::string& title);
Trace(const eckit::CodeLocation& loc, const std::string& title, const Labels& labels);

private:
std::vector<std::unique_ptr<TraceHook>> hooks_;
};

} // namespace io
} // namespace atlas

#include "atlas_io/detail/BlackMagic.h"

#define ATLAS_IO_TRACE(...) __ATLAS_IO_TYPE(::atlas::io::Trace, Here() __ATLAS_IO_COMMA_ARGS(__VA_ARGS__))
#define ATLAS_IO_TRACE_SCOPE(...) __ATLAS_IO_TYPE_SCOPE(::atlas::io::Trace, Here() __ATLAS_IO_COMMA_ARGS(__VA_ARGS__))
99 changes: 99 additions & 0 deletions atlas_io/eckit_codec_adaptor/src/atlas_io/atlas-io.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* (C) Copyright 2023- ECMWF.
*
* This software is licensed under the terms of the Apache Licence Version 2.0
* which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
* In applying this licence, ECMWF does not waive the privileges and immunities
* granted to it by virtue of its status as an intergovernmental organisation
* nor does it submit to any jurisdiction.
*/

#pragma once

#include "eckit/codec/codec.h"

namespace atlas::io {

// Encoding/Decoding
using Metadata = ::eckit::codec::Metadata;
using DataType = ::eckit::codec::DataType;
using Data = ::eckit::codec::Data;
using Encoder = ::eckit::codec::Encoder;
using Decoder = ::eckit::codec::Decoder;

// Record
using Record = ::eckit::codec::Record;
using RecordWriter = ::eckit::codec::RecordWriter;
using RecordPrinter = ::eckit::codec::RecordPrinter;
using RecordItemReader = ::eckit::codec::RecordItemReader;
using RecordReader = ::eckit::codec::RecordReader;

// I/O
using Session = ::eckit::codec::Session;
using Mode = ::eckit::codec::Mode;
using Stream = ::eckit::codec::Stream;
using FileStream = ::eckit::codec::FileStream;
using InputFileStream = ::eckit::codec::InputFileStream;
using OutputFileStream = ::eckit::codec::OutputFileStream;

// Array
using ArrayReference = ::eckit::codec::ArrayReference;
using ArrayMetadata = ::eckit::codec::ArrayMetadata;
using ArrayShape = ::eckit::codec::ArrayShape;

// Exceptions
using Exception = ::eckit::codec::Exception;
using NotEncodable = ::eckit::codec::NotEncodable;
using NotDecodable = ::eckit::codec::NotDecodable;
using InvalidRecord = ::eckit::codec::InvalidRecord;
using DataCorruption = ::eckit::codec::DataCorruption;
using WriteError = ::eckit::codec::WriteError;

// Type traits
template <class T, class A>
static constexpr bool is_interpretable() {
return ::eckit::codec::is_interpretable<T,A>();
}
template <typename T>
static constexpr bool is_encodable() {
return ::eckit::codec::is_encodable<T>();
}
template <typename T>
static constexpr bool is_decodable() {
return ::eckit::codec::is_decodable<T>();
}
template <typename T>
static constexpr bool can_encode_metadata() {
return ::eckit::codec::can_encode_metadata<T>();
}
template <typename T>
static constexpr bool can_encode_data() {
return ::eckit::codec::can_encode_metadata<T>();
}

namespace tag {
using disable_static_assert = ::eckit::codec::tag::disable_static_assert;
using enable_static_assert = ::eckit::codec::tag::enable_static_assert;
}

// Functions
using ::eckit::codec::ref;
using ::eckit::codec::copy;
using ::eckit::codec::encode;
using ::eckit::codec::decode;
using ::eckit::codec::interprete;
using ::eckit::codec::link;
using ::eckit::codec::make_datatype;
// template <typename DATATYPE>
// using make_datatype = eckit::codec::make_datatype<DATATYPE>;

namespace defaults {
using ::eckit::codec::defaults::compression_algorithm;
using ::eckit::codec::defaults::checksum_algorithm;
using ::eckit::codec::defaults::checksum_read;
using ::eckit::codec::defaults::checksum_write;
}
}

#define ATLAS_IO_ASSERT(X) ASSERT(X)
#define ATLAS_IO_ASSERT_MSG(X, M) ASSERT_MSG(X, M)
101 changes: 101 additions & 0 deletions atlas_io/eckit_codec_adaptor/src/atlas_io/detail/BlackMagic.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* (C) Copyright 2013 ECMWF.
*
* This software is licensed under the terms of the Apache Licence Version 2.0
* which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
* In applying this licence, ECMWF does not waive the privileges and immunities
* granted to it by virtue of its status as an intergovernmental organisation
* nor does it submit to any jurisdiction.
*/

#pragma once

// This file contains preprocessor black magic. It contains macros that
// can return the number of arguments passed

//-----------------------------------------------------------------------------------------------------------
// Public

/// Returns the number of passed arguments
#define __ATLAS_IO_NARG(...)

/// Splice a and b together
#define __ATLAS_IO_SPLICE(a, b)

#define __ATLAS_IO_STRINGIFY(a) a

#define __ATLAS_IO_TYPE(Type, ...)
#define __ATLAS_IO_TYPE_SCOPE(Type, ...)

//-----------------------------------------------------------------------------------------------------------
// Details

// Undefine these, to be redefined further down.
#undef __ATLAS_IO_NARG
#undef __ATLAS_IO_SPLICE
#undef __ATLAS_IO_TYPE
#undef __ATLAS_IO_TYPE_SCOPE

#define __ATLAS_IO_REVERSE 5, 4, 3, 2, 1, 0
#define __ATLAS_IO_ARGN(_1, _2, _3, _4, _5, N, ...) N
#define __ATLAS_IO_NARG__(dummy, ...) __ATLAS_IO_ARGN(__VA_ARGS__)
#define __ATLAS_IO_NARG_(...) __ATLAS_IO_NARG__(dummy, ##__VA_ARGS__, __ATLAS_IO_REVERSE)
#define __ATLAS_IO_SPLICE(a, b) __ATLAS_IO_SPLICE_1(a, b)
#define __ATLAS_IO_SPLICE_1(a, b) __ATLAS_IO_SPLICE_2(a, b)
#define __ATLAS_IO_SPLICE_2(a, b) a##b

#define __ATLAS_IO_ARG16(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, ...) _15
#define __ATLAS_IO_HAS_COMMA(...) __ATLAS_IO_ARG16(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0)
#define __ATLAS_IO_TRIGGER_PARENTHESIS(...) ,
#define __ATLAS_IO_ISEMPTY(...) \
__ATLAS_IO_ISEMPTY_(/* test if there is just one argument, eventually an empty \
one */ \
__ATLAS_IO_HAS_COMMA(__VA_ARGS__), /* test if \
_TRIGGER_PARENTHESIS_ \
together with the \
argument adds a comma */ \
__ATLAS_IO_HAS_COMMA( \
__ATLAS_IO_TRIGGER_PARENTHESIS __VA_ARGS__), /* test if the argument together with \
a parenthesis adds a comma */ \
__ATLAS_IO_HAS_COMMA(__VA_ARGS__(/*empty*/)), /* test if placing it between \
__ATLAS_IO_TRIGGER_PARENTHESIS and the \
parenthesis adds a comma */ \
__ATLAS_IO_HAS_COMMA(__ATLAS_IO_TRIGGER_PARENTHESIS __VA_ARGS__(/*empty*/)))

#define __ATLAS_IO_PASTE5(_0, _1, _2, _3, _4) _0##_1##_2##_3##_4
#define __ATLAS_IO_ISEMPTY_(_0, _1, _2, _3) \
__ATLAS_IO_HAS_COMMA(__ATLAS_IO_PASTE5(__ATLAS_IO_IS_EMPTY_CASE_, _0, _1, _2, _3))
#define __ATLAS_IO_IS_EMPTY_CASE_0001 ,

#define __ATLAS_IO_NARG(...) __ATLAS_IO_SPLICE(__ATLAS_IO_CALL_NARG_, __ATLAS_IO_ISEMPTY(__VA_ARGS__))(__VA_ARGS__)
#define __ATLAS_IO_CALL_NARG_1(...) 0
#define __ATLAS_IO_CALL_NARG_0 __ATLAS_IO_NARG_

#define __ATLAS_IO_COMMA_ARGS(...) \
__ATLAS_IO_SPLICE(__ATLAS_IO_COMMA_ARGS_, __ATLAS_IO_ISEMPTY(__VA_ARGS__))(__VA_ARGS__)
#define __ATLAS_IO_COMMA_ARGS_1(...)
#define __ATLAS_IO_COMMA_ARGS_0(...) , __VA_ARGS__

#define __ATLAS_IO_ARGS_OR_DUMMY(...) \
__ATLAS_IO_SPLICE(__ATLAS_IO_ARGS_OR_DUMMY_, __ATLAS_IO_ISEMPTY(__VA_ARGS__)) \
(__VA_ARGS__)
#define __ATLAS_IO_ARGS_OR_DUMMY_0(...) __VA_ARGS__
#define __ATLAS_IO_ARGS_OR_DUMMY_1(...) 0

#define __ATLAS_IO_TYPE(Type, ...) \
__ATLAS_IO_SPLICE(__ATLAS_IO_TYPE_, __ATLAS_IO_ISEMPTY(__VA_ARGS__)) \
(Type, __ATLAS_IO_ARGS_OR_DUMMY(__VA_ARGS__))
#define __ATLAS_IO_TYPE_1(Type, dummy) Type __ATLAS_IO_SPLICE(__variable_, __LINE__)
#define __ATLAS_IO_TYPE_0(Type, ...) Type __ATLAS_IO_SPLICE(__variable_, __LINE__)(__VA_ARGS__)

#define __ATLAS_IO_TYPE_SCOPE(Type, ...) \
__ATLAS_IO_SPLICE(__ATLAS_IO_TYPE_SCOPE_, __ATLAS_IO_ISEMPTY(__VA_ARGS__)) \
(Type, __ATLAS_IO_ARGS_OR_DUMMY(__VA_ARGS__))
#define __ATLAS_IO_TYPE_SCOPE_1(Type, ...) \
for (bool __ATLAS_IO_SPLICE(__done_, __LINE__) = false; __ATLAS_IO_SPLICE(__done_, __LINE__) != true;) \
for (Type __ATLAS_IO_SPLICE(__variable_, __LINE__); __ATLAS_IO_SPLICE(__done_, __LINE__) != true; \
__ATLAS_IO_SPLICE(__done_, __LINE__) = true)
#define __ATLAS_IO_TYPE_SCOPE_0(Type, ...) \
for (bool __ATLAS_IO_SPLICE(__done_, __LINE__) = false; __ATLAS_IO_SPLICE(__done_, __LINE__) != true;) \
for (Type __ATLAS_IO_SPLICE(__variable_, __LINE__)(__VA_ARGS__); __ATLAS_IO_SPLICE(__done_, __LINE__) != true; \
__ATLAS_IO_SPLICE(__done_, __LINE__) = true)
2 changes: 1 addition & 1 deletion atlas_io/tests/TestEnvironment.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
#include "eckit/types/Types.h"

#include "atlas_io/atlas-io.h"
#include "atlas_io/detail/BlackMagic.h"
#include "atlas_io/Trace.h"

namespace atlas {
namespace test {
Expand Down
Loading

0 comments on commit 20785f8

Please sign in to comment.