File: odc_ls.cc

package info (click to toggle)
odc 1.6.2-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,140 kB
  • sloc: cpp: 21,984; f90: 3,707; sh: 966; ansic: 477; python: 389; makefile: 33
file content (164 lines) | stat: -rw-r--r-- 5,178 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/**
 * To build this program, please make sure to reference linked libraries:
 *
 *     g++ -std=c++11 -leckit -lodccore -o odc-cpp-ls odc_ls.cc
 */

#include <math.h>
#include <cstdint>
#include <iomanip>
#include <iostream>
#include <numeric>
#include <vector>

#include "eckit/runtime/Main.h"

#include "odc/api/Odb.h"

void usage() {
    std::cerr << "Usage:\n    odc-cpp-ls <odb2 file>" << std::endl << std::endl;
}

void write_header(int i, odc::api::ColumnInfo col) {
    int padding = col.decodedSize - floor(log10(abs(i + 1))) + 2;
    std::cout << (i + 1) << ". " << std::left << std::setw(padding) << col.name << "\t";
}

void write_data(size_t nrows, size_t ncols, std::vector<odc::api::ColumnInfo> columnInfo,
                std::vector<odc::api::StridedData> strides, std::vector<int> nbits) {
    long integer_missing  = odc::api::Settings::integerMissingValue();
    double double_missing = odc::api::Settings::doubleMissingValue();

    for (size_t row = 0; row < nrows; ++row) {
        for (size_t col = 0; col < ncols; ++col) {
            switch (columnInfo[col].type) {
                case odc::api::INTEGER: {
                    int64_t val = *reinterpret_cast<const int64_t*>(strides[col][row]);
                    if (val == integer_missing) {
                        std::cout << ".";
                    }
                    else {
                        std::cout << std::left << std::setw(columnInfo[col].decodedSize) << val;
                    }
                    break;
                }
                case odc::api::BITFIELD: {
                    int64_t val = *reinterpret_cast<const int64_t*>(strides[col][row]);
                    for (int bit = nbits[col] - 1; bit >= 0; --bit) {
                        std::cout << ((val & (1 << bit)) ? "1" : "0");
                    }
                    break;
                }
                case odc::api::REAL:
                case odc::api::DOUBLE: {
                    double val = *reinterpret_cast<const double*>(strides[col][row]);
                    if (val == double_missing) {
                        std::cout << ".";
                    }
                    else {
                        std::cout << std::left << std::setw(columnInfo[col].decodedSize) << val;
                    }
                    break;
                }
                    std::cout << *reinterpret_cast<const int64_t*>(strides[col][row]);
                    break;
                case odc::api::STRING:
                    std::cout << std::left << std::setw(columnInfo[col].decodedSize)
                              << std::string(strides[col][row],
                                             ::strnlen(strides[col][row], columnInfo[col].decodedSize));
                    break;
                default:
                    ASSERT(false);
            };
            std::cout << "\t";
        }
        std::cout << std::endl;
    }
}

int main(int argc, char** argv) {
    if (argc != 2) {
        usage();
        return 1;
    }

    char* path = argv[1];

    eckit::Main::initialise(argc, argv);

    // Initialise library

    odc::api::Settings::treatIntegersAsDoubles(false);

    // Open the specified ODB file

    odc::api::Reader reader(path);

    // Iterate through the frames

    odc::api::Frame frame;
    while ((frame = reader.next())) {

        // Properties of this frame

        size_t ncols           = frame.columnCount();
        size_t nrows           = frame.rowCount();
        const auto& columnInfo = frame.columnInfo();

        // Print headers & determine storage requirements

        size_t row_size = 0;
        size_t i;

        for (i = 0; i < frame.columnCount(); ++i) {
            const auto& col(columnInfo[i]);

            write_header(i, col);

            row_size += col.decodedSize;
        }

        std::cout << std::endl;

        // Allocate storage required

        size_t storage_size = row_size * nrows;
        std::vector<char> buffer(storage_size);

        // Decoder prerequisites

        std::vector<std::string> columns;
        std::vector<odc::api::StridedData> strides;
        std::vector<int> nbits;

        char* ptr = &buffer[0];
        for (const auto& col : columnInfo) {
            columns.push_back(col.name);
            strides.emplace_back(odc::api::StridedData{ptr, nrows, col.decodedSize, col.decodedSize});
            ptr += nrows * col.decodedSize;

            // Bits for formatting bitfields
            if (col.type == odc::api::BITFIELD) {
                nbits.push_back(std::accumulate(col.bitfield.begin(), col.bitfield.end(), 0,
                                                [](int l, const odc::api::ColumnInfo::Bit& r) { return l + r.size; }));
            }
            else {
                nbits.push_back(0);
            }
        }

        ASSERT(ptr == (&buffer[0] + storage_size));

        // Decode the data

        int nthreads = 4;
        odc::api::Decoder decoder(columns, strides);
        decoder.decode(frame, nthreads);

        // Iterate through the decoded data, and print it

        write_data(nrows, ncols, columnInfo, strides, nbits);
    }

    return 0;
}