Coverage Report

Created: 2024-11-21 11:46

/root/doris/be/src/geo/geo_tobinary.cpp
Line
Count
Source (jump to first uncovered line)
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
#include "geo_tobinary.h"
19
20
#include <cstddef>
21
#include <sstream>
22
#include <vector>
23
24
#include "geo/ByteOrderValues.h"
25
#include "geo/geo_common.h"
26
#include "geo/machine.h"
27
#include "geo/wkt_parse_type.h"
28
#include "geo_tobinary_type.h"
29
#include "geo_types.h"
30
#include "iomanip"
31
32
namespace doris {
33
34
0
bool toBinary::geo_tobinary(GeoShape* shape, std::string* result) {
35
0
    ToBinaryContext ctx;
36
0
    std::stringstream result_stream;
37
0
    ctx.outStream = &result_stream;
38
0
    if (toBinary::write(shape, &ctx)) {
39
0
        std::stringstream hex_stream;
40
0
        hex_stream << std::hex << std::setfill('0');
41
0
        result_stream.seekg(0);
42
0
        unsigned char c;
43
0
        while (result_stream.read(reinterpret_cast<char*>(&c), 1)) {
44
0
            hex_stream << std::setw(2) << static_cast<int>(c);
45
0
        }
46
        //for compatibility with postgres
47
0
        *result = "\\x" + hex_stream.str();
48
0
        return true;
49
0
    }
50
0
    return false;
51
0
}
52
53
0
bool toBinary::write(GeoShape* shape, ToBinaryContext* ctx) {
54
0
    switch (shape->type()) {
55
0
    case GEO_SHAPE_POINT: {
56
0
        return writeGeoPoint((GeoPoint*)(shape), ctx);
57
0
    }
58
0
    case GEO_SHAPE_LINE_STRING: {
59
0
        return writeGeoLine((GeoLine*)(shape), ctx);
60
0
    }
61
0
    case GEO_SHAPE_POLYGON: {
62
0
        return writeGeoPolygon((GeoPolygon*)(shape), ctx);
63
0
    }
64
0
    default:
65
0
        return false;
66
0
    }
67
0
}
68
69
0
bool toBinary::writeGeoPoint(GeoPoint* point, ToBinaryContext* ctx) {
70
0
    writeByteOrder(ctx);
71
0
    writeGeometryType(wkbType::wkbPoint, ctx);
72
0
    GeoCoordinateList p = point->to_coords();
73
74
0
    writeCoordinateList(p, false, ctx);
75
0
    return true;
76
0
}
77
78
0
bool toBinary::writeGeoLine(GeoLine* line, ToBinaryContext* ctx) {
79
0
    writeByteOrder(ctx);
80
0
    writeGeometryType(wkbType::wkbLine, ctx);
81
0
    GeoCoordinateList p = line->to_coords();
82
83
0
    writeCoordinateList(p, true, ctx);
84
0
    return true;
85
0
}
86
87
0
bool toBinary::writeGeoPolygon(doris::GeoPolygon* polygon, ToBinaryContext* ctx) {
88
0
    writeByteOrder(ctx);
89
0
    writeGeometryType(wkbType::wkbPolygon, ctx);
90
0
    writeInt(polygon->numLoops(), ctx);
91
0
    std::unique_ptr<GeoCoordinateListList> coordss(polygon->to_coords());
92
93
0
    for (int i = 0; i < coordss->list.size(); ++i) {
94
0
        writeCoordinateList(*coordss->list[i], true, ctx);
95
0
    }
96
0
    return true;
97
0
}
98
99
0
void toBinary::writeByteOrder(ToBinaryContext* ctx) {
100
0
    ctx->byteOrder = getMachineByteOrder();
101
0
    if (ctx->byteOrder == 1) {
102
0
        ctx->buf[0] = byteOrder::wkbNDR;
103
0
    } else {
104
0
        ctx->buf[0] = byteOrder::wkbXDR;
105
0
    }
106
107
0
    ctx->outStream->write(reinterpret_cast<char*>(ctx->buf), 1);
108
0
}
109
110
0
void toBinary::writeGeometryType(int typeId, ToBinaryContext* ctx) {
111
0
    writeInt(typeId, ctx);
112
0
}
113
114
0
void toBinary::writeInt(int val, ToBinaryContext* ctx) {
115
0
    ByteOrderValues::putInt(val, ctx->buf, ctx->byteOrder);
116
0
    ctx->outStream->write(reinterpret_cast<char*>(ctx->buf), 4);
117
0
}
118
119
void toBinary::writeCoordinateList(const GeoCoordinateList& coords, bool sized,
120
0
                                   ToBinaryContext* ctx) {
121
0
    std::size_t size = coords.list.size();
122
123
0
    if (sized) {
124
0
        writeInt(static_cast<int>(size), ctx);
125
0
    }
126
0
    for (std::size_t i = 0; i < size; i++) {
127
0
        GeoCoordinate coord = coords.list[i];
128
0
        writeCoordinate(coord, ctx);
129
0
    }
130
0
}
131
132
0
void toBinary::writeCoordinate(GeoCoordinate& coords, ToBinaryContext* ctx) {
133
0
    ByteOrderValues::putDouble(coords.x, ctx->buf, ctx->byteOrder);
134
0
    ctx->outStream->write(reinterpret_cast<char*>(ctx->buf), 8);
135
0
    ByteOrderValues::putDouble(coords.y, ctx->buf, ctx->byteOrder);
136
0
    ctx->outStream->write(reinterpret_cast<char*>(ctx->buf), 8);
137
0
}
138
139
} // namespace doris