template<> NValue NValue::callUnary<FUNC_VOLT_POLYGONFROMTEXT>() const { bool is_shell = true; if (isNull()) { return NValue::getNullValue(VALUE_TYPE_GEOGRAPHY); } int32_t textLength; const char* textData = getObject_withoutNull(&textLength); const std::string wkt(textData, textLength); // Discard whitespace, but return commas or parentheses as tokens Tokenizer tokens(wkt, boost::char_separator<char>(" \f\n\r\t\v", ",()")); Tokenizer::iterator it = tokens.begin(); Tokenizer::iterator end = tokens.end(); if (! boost::iequals(*it, "polygon")) { throwInvalidWktPoly("does not start with POLYGON keyword"); } ++it; if (! boost::iequals(*it, "(")) { throwInvalidWktPoly("missing left parenthesis after POLYGON keyword"); } ++it; std::size_t length = Polygon::serializedLengthNoLoops(); std::vector<std::unique_ptr<S2Loop> > loops; while (it != end) { loops.push_back(std::unique_ptr<S2Loop>(new S2Loop())); readLoop(is_shell, wkt, it, end, loops.back().get()); // Only the first loop is a shell. is_shell = false; length += Loop::serializedLength(loops.back()->num_vertices()); if (*it == ",") { ++it; } else if (*it == ")") { ++it; break; } else { throwInvalidWktPoly("unexpected token: '" + (*it) + "'"); } } if (it != end) { // extra stuff after input throwInvalidWktPoly("unrecognized input after WKT: '" + (*it) + "'"); } NValue nval = ValueFactory::getUninitializedTempGeographyValue(length); char* storage = const_cast<char*>(ValuePeeker::peekObjectValue(nval)); Polygon poly; poly.init(&loops); // polygon takes ownership of loops here. SimpleOutputSerializer output(storage, length); poly.saveToBuffer(output); return nval; }
template<> NValue NValue::callUnary<FUNC_VOLT_POINTFROMTEXT>() const { if (isNull()) { return NValue::getNullValue(VALUE_TYPE_POINT); } int32_t textLength; const char* textData = getObject_withoutNull(&textLength); std::string wkt(textData, textLength); // Discard whitespace, but return commas or parentheses as tokens Tokenizer tokens(wkt, boost::char_separator<char>(" \f\n\r\t\v", ",()")); Tokenizer::iterator it = tokens.begin(); Tokenizer::iterator end = tokens.end(); if (! boost::iequals(*it, "point")) { throwInvalidWktPoint(wkt); } ++it; if (! boost::iequals(*it, "(")) { throwInvalidWktPoint(wkt); } ++it; GeographyPointValue::Coord lng = stringToCoord(POINT, wkt, *it); ++it; GeographyPointValue::Coord lat = stringToCoord(POINT, wkt, *it); ++it; if ( lng < -180.0 || lng > 180.0) { throwInvalidPointLongitude(wkt); } if (lat < -90.0 || lat > 90.0 ) { throwInvalidPointLatitude(wkt); } if (! boost::iequals(*it, ")")) { throwInvalidWktPoint(wkt); } ++it; if (it != end) { throwInvalidWktPoint(wkt); } NValue returnValue(VALUE_TYPE_POINT); returnValue.getGeographyPointValue() = GeographyPointValue(lng, lat); return returnValue; }
template<> NValue NValue::callUnary<FUNC_VOLT_POLYGONFROMVALIDTEXT>() const { if (isNull()) { return NValue::getNullValue(VALUE_TYPE_GEOGRAPHY); } int32_t textLength; const char* textData = getObject_withoutNull(&textLength); const std::string wkt(textData, textLength); return polygonFromText(wkt, true); }
/* * Produce a debugging string describing an NValue. */ std::string NValue::debug() const { const ValueType type = getValueType(); if (isNull()) { return "<NULL>"; } std::ostringstream buffer; std::string out_val; const char* ptr; int64_t addr; buffer << getTypeName(type) << "::"; switch (type) { case VALUE_TYPE_BOOLEAN: buffer << (getBoolean() ? "true" : "false"); break; case VALUE_TYPE_TINYINT: buffer << static_cast<int32_t>(getTinyInt()); break; case VALUE_TYPE_SMALLINT: buffer << getSmallInt(); break; case VALUE_TYPE_INTEGER: buffer << getInteger(); break; case VALUE_TYPE_BIGINT: buffer << getBigInt(); break; case VALUE_TYPE_DOUBLE: buffer << getDouble(); break; case VALUE_TYPE_VARCHAR: { int32_t length; ptr = getObject_withoutNull(&length); addr = reinterpret_cast<int64_t>(ptr); out_val = std::string(ptr, length); buffer << "[" << length << "]"; buffer << "\"" << out_val << "\"[@" << addr << "]"; break; } case VALUE_TYPE_VARBINARY: { int32_t length; ptr = getObject_withoutNull(&length); addr = reinterpret_cast<int64_t>(ptr); out_val = std::string(ptr, length); buffer << "[" << length << "]"; buffer << "-bin[@" << addr << "]"; break; } case VALUE_TYPE_DECIMAL: buffer << createStringFromDecimal(); break; case VALUE_TYPE_TIMESTAMP: { try { std::stringstream ss; streamTimestamp(ss); buffer << ss.str(); } catch (const SQLException &) { buffer << "<out of range timestamp:" << getBigInt() << ">"; } catch (...) { buffer << "<exception when converting timestamp:" << getBigInt() << ">"; } break; } case VALUE_TYPE_POINT: buffer << getGeographyPointValue().toString(); break; case VALUE_TYPE_GEOGRAPHY: buffer << getGeographyValue().toString(); break; default: buffer << "(no details)"; break; } std::string ret(buffer.str()); return (ret); }