blob: 0e64c001687e416e1044d171897c257cedd673ad [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#include "geo_tobinary.h"
#include <cstddef>
#include <sstream>
#include <vector>
#include "geo/ByteOrderValues.h"
#include "geo/geo_common.h"
#include "geo/machine.h"
#include "geo/wkt_parse_type.h"
#include "geo_tobinary_type.h"
#include "geo_types.h"
#include "iomanip"
namespace doris {
bool toBinary::geo_tobinary(GeoShape* shape, std::string* result) {
ToBinaryContext ctx;
std::stringstream result_stream;
ctx.outStream = &result_stream;
if (toBinary::write(shape, &ctx)) {
std::stringstream hex_stream;
hex_stream << std::hex << std::setfill('0');
result_stream.seekg(0);
unsigned char c;
while (result_stream.read(reinterpret_cast<char*>(&c), 1)) {
hex_stream << std::setw(2) << static_cast<int>(c);
}
//for compatibility with postgres
*result = "\\x" + hex_stream.str();
return true;
}
return false;
}
bool toBinary::write(GeoShape* shape, ToBinaryContext* ctx) {
switch (shape->type()) {
case GEO_SHAPE_POINT: {
return writeGeoPoint((GeoPoint*)(shape), ctx);
}
case GEO_SHAPE_LINE_STRING: {
return writeGeoLine((GeoLine*)(shape), ctx);
}
case GEO_SHAPE_POLYGON: {
return writeGeoPolygon((GeoPolygon*)(shape), ctx);
}
default:
return false;
}
}
bool toBinary::writeGeoPoint(GeoPoint* point, ToBinaryContext* ctx) {
writeByteOrder(ctx);
writeGeometryType(wkbType::wkbPoint, ctx);
GeoCoordinateList p = point->to_coords();
writeCoordinateList(p, false, ctx);
return true;
}
bool toBinary::writeGeoLine(GeoLine* line, ToBinaryContext* ctx) {
writeByteOrder(ctx);
writeGeometryType(wkbType::wkbLine, ctx);
GeoCoordinateList p = line->to_coords();
writeCoordinateList(p, true, ctx);
return true;
}
bool toBinary::writeGeoPolygon(doris::GeoPolygon* polygon, ToBinaryContext* ctx) {
writeByteOrder(ctx);
writeGeometryType(wkbType::wkbPolygon, ctx);
writeInt(polygon->numLoops(), ctx);
std::unique_ptr<GeoCoordinateListList> coordss(polygon->to_coords());
for (int i = 0; i < coordss->list.size(); ++i) {
writeCoordinateList(*coordss->list[i], true, ctx);
}
return true;
}
void toBinary::writeByteOrder(ToBinaryContext* ctx) {
ctx->byteOrder = getMachineByteOrder();
if (ctx->byteOrder == 1) {
ctx->buf[0] = byteOrder::wkbNDR;
} else {
ctx->buf[0] = byteOrder::wkbXDR;
}
ctx->outStream->write(reinterpret_cast<char*>(ctx->buf), 1);
}
void toBinary::writeGeometryType(int typeId, ToBinaryContext* ctx) {
writeInt(typeId, ctx);
}
void toBinary::writeInt(int val, ToBinaryContext* ctx) {
ByteOrderValues::putInt(val, ctx->buf, ctx->byteOrder);
ctx->outStream->write(reinterpret_cast<char*>(ctx->buf), 4);
}
void toBinary::writeCoordinateList(const GeoCoordinateList& coords, bool sized,
ToBinaryContext* ctx) {
std::size_t size = coords.list.size();
if (sized) {
writeInt(static_cast<int>(size), ctx);
}
for (std::size_t i = 0; i < size; i++) {
GeoCoordinate coord = coords.list[i];
writeCoordinate(coord, ctx);
}
}
void toBinary::writeCoordinate(GeoCoordinate& coords, ToBinaryContext* ctx) {
ByteOrderValues::putDouble(coords.x, ctx->buf, ctx->byteOrder);
ctx->outStream->write(reinterpret_cast<char*>(ctx->buf), 8);
ByteOrderValues::putDouble(coords.y, ctx->buf, ctx->byteOrder);
ctx->outStream->write(reinterpret_cast<char*>(ctx->buf), 8);
}
} // namespace doris