// // Copyright (C) 2007 Refractions Research, Inc. // // This library is free software; you can redistribute it and/or // modify it under the terms of version 2.1 of the GNU Lesser // General Public License as published by the Free Software Foundation. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // #ifndef FDOUTILITY_H_INCLUDED #define FDOUTILITY_H_INCLUDED // FDO #include // std #include #include #include #include #include #include // boost #include #include #include #ifdef _MSC_VER #pragma warning(disable:4251 4275 4996) #endif // _MSC_VER /// Simple FDO utility package used in PostGIS provider for FDO samples. /// namespace fdoutility { /////////////////////////////////////////////////////////////////////////////// // Operations on strings of characters /////////////////////////////////////////////////////////////////////////////// std::wstring towstring(std::string const& source) { std::wstring result(source.size(), wchar_t(0)); typedef std::ctype ctype_t; const ctype_t& ct = std::use_facet(std::locale()); ct.widen(source.data(), source.data() + source.size(), &(*result.begin())); return result; } std::string tostring(std::wstring const& source) { std::string result(source.size(), char(0)); typedef std::ctype ctype_t; const ctype_t& ct = std::use_facet(std::locale()); ct.narrow(source.data(), source.data() + source.size(), L'\u00B6', &(*result.begin())); return result; } std::ostream& operator<<(std::ostream& out, const std::wstring& value) { out << tostring(value); return out; } std::wostream& operator<<(std::wostream& out, const std::string& value) { out << towstring(value); return out; } template std::wostream& operator<<(std::wostream& os, std::pair const& prop) { os << std::setw(4) << L"" << prop.first << L": " << prop.second << '\n'; return os; } template std::wostream& operator<<(std::wostream& os, std::pair const& prop) { os << std::setw(4) << L"" << prop.first << L": " << std::boolalpha << prop.second << '\n'; return os; } /////////////////////////////////////////////////////////////////////////////// // Utilities for FDO types and operations /////////////////////////////////////////////////////////////////////////////// std::wostream& operator<<(std::wostream& os, FdoConnectionState state) { switch(state) { case FdoConnectionState_Open: os << L"Open"; break; case FdoConnectionState_Closed: os << L"Closed"; break; case FdoConnectionState_Busy: os << L"Busy"; break; case FdoConnectionState_Pending: os << L"Pending"; break; default: assert(false); // NEVER GET HERE } return os; } std::wostream& operator<<(std::wostream& os, FdoDataType type) { switch(type) { case FdoDataType_Boolean: os << L"Boolean"; break; case FdoDataType_Byte: os << L"Byte"; break; case FdoDataType_DateTime: os << L"DateTime"; break; case FdoDataType_Decimal: os << L"Decimal"; break; case FdoDataType_Double: os << L"Double"; break; case FdoDataType_Int16: os << L"Int16"; break; case FdoDataType_Int32: os << L"Int32"; break; case FdoDataType_Int64: os << L"Int64"; break; case FdoDataType_Single: os << L"Single"; break; case FdoDataType_String: os << L"String"; break; case FdoDataType_BLOB: os << L"BLOB"; break; case FdoDataType_CLOB: os << L"CLOB"; default: assert(false); // NEVER GET HERE } return os; } template FdoPtr create_connection(T const& provider) { // Get connection manager instance FdoPtr mgr; mgr = FdoFeatureAccessManager::GetConnectionManager(); assert(0 != mgr ); // Create connection FdoPtr conn; conn = mgr->CreateConnection(provider.c_str()); assert(0 != conn); return conn; } FdoPtr create_connection(std::string const& provider) { return create_connection(towstring(provider)); } void list_properties(std::wostream& os, FdoIPropertyDictionary* dict) { assert(0 != dict); FdoInt32 dictSize = 0; FdoString** names = dict->GetPropertyNames(dictSize); assert(0 != names); // List properties std::wstring tmp; std::wstring none(L""); for (FdoInt32 i = 0; i < dictSize; i++) { FdoString* property = names[i]; assert(0 != property); FdoString* value = dict->GetProperty(property); assert(0 != value); os << std::setw(2) << (i + 1) << L". " << property << L" ( " << (dict->IsPropertyRequired(property) ? L"R " : none) << (dict->IsPropertyProtected(property) ? L"P " : none) << (dict->IsPropertyEnumerable(property) ? L"E " : none) << (dict->IsPropertyFileName(property) ? L"FN " : none) << (dict->IsPropertyFilePath(property) ? L"FP " : none) << (dict->IsPropertyDatastoreName(property) ? L"D " : none) << L") = " << value << std::endl; // Default values tmp = dict->GetPropertyDefault(property); if (!tmp.empty()) os << L"Default value: " << tmp << std::endl; // Enumerable possible property values if (dict->IsPropertyEnumerable(property)) { FdoInt32 valuesSize = 0; FdoString** values = dict->EnumeratePropertyValues(property, valuesSize); assert(0 != values); if (valuesSize > 1) { for (FdoInt32 j = 0; j < valuesSize; j++) { assert(0 != values[j]); os << values[j] << (j == (valuesSize - 1) ? L" " : L", "); } os << std::endl; } } } } /////////////////////////////////////////////////////////////////////////////// // Operations on binary data /////////////////////////////////////////////////////////////////////////////// void bytes_to_hex(std::vector const& bytes, std::string& hexstr) { typedef std::vector::size_type size_type; std::ostringstream oss; oss << std::setfill('0'); for(size_type i = 0; i < bytes.size(); ++i) { oss << std::setw(2) << std::hex << static_cast(bytes[i]); } hexstr = oss.str(); } void hex_to_bytes(std::string const& hexstr, std::vector& bytes) { bytes.clear(); for(std::string::size_type i = 0; i < hexstr.size() / 2; ++i) { std::istringstream iss(hexstr.substr(i * 2, 2)); unsigned int n; iss >> std::hex >> n; bytes.push_back(static_cast(n)); } } struct endian_big_tag; struct endian_little_tag; template struct convert_endian_policy; template struct convert_endian_policy { static const size_t begin = sizeof(Target); static const size_t end = 0; static void step(size_t& current) { --current; } static size_t indexof(size_t const& current) { return current - 1; } static size_t offset(size_t const& current) { return current - 1; } }; template struct convert_endian_policy { static const size_t begin = 0; static const size_t end = sizeof(Target); static void step(size_t& current) { ++current; } static size_t indexof(size_t const& current) { return current; } static size_t offset(size_t const& current) { return end - (current + 1); } }; // // TODO: Add Boost utils for compile-time detection of endianness // #ifdef BOOST_BIG_ENDIAN template < class Target, class Traits = convert_endian_policy > #else template // BOOST_LITTLE_ENDIAN < class Target, class Traits = convert_endian_policy > #endif // BOOST_BIG_ENDIAN struct read_data { static Target from(boost::uint8_t const* bytes) { Target result = Target(); for (size_t bn = Traits::begin; bn != Traits::end; Traits::step(bn)) { size_t const index = Traits::indexof(bn); size_t const shift = (Traits::offset(bn)) << 3; result |= (Target)(bytes[index] << shift) & 0xff; } return result; } }; template<> struct read_data { static double from(boost::uint8_t const* bytes) { BOOST_STATIC_ASSERT(sizeof(boost::int64_t) == sizeof(double)); boost::int64_t tmp = read_data::from(bytes); double data = double(); std::memcpy(&data, &tmp, sizeof(double)); return data; } }; /////////////////////////////////////////////////////////////////////////////// // Following functions have been stolen from PostGIS // and are used for testing purpose only, as a reference // // TODO: Remove it after tests // /////////////////////////////////////////////////////////////////////////////// unsigned char postgis_parse_hex(char const* str) { /* do this a little brute force to make it faster */ unsigned char result_high = 0; unsigned char result_low = 0; switch (str[0]) { case '0' : result_high = 0; break; case '1' : result_high = 1; break; case '2' : result_high = 2; break; case '3' : result_high = 3; break; case '4' : result_high = 4; break; case '5' : result_high = 5; break; case '6' : result_high = 6; break; case '7' : result_high = 7; break; case '8' : result_high = 8; break; case '9' : result_high = 9; break; case 'A' : result_high = 10; break; case 'B' : result_high = 11; break; case 'C' : result_high = 12; break; case 'D' : result_high = 13; break; case 'E' : result_high = 14; break; case 'F' : result_high = 15; break; } switch (str[1]) { case '0' : result_low = 0; break; case '1' : result_low = 1; break; case '2' : result_low = 2; break; case '3' : result_low = 3; break; case '4' : result_low = 4; break; case '5' : result_low = 5; break; case '6' : result_low = 6; break; case '7' : result_low = 7; break; case '8' : result_low = 8; break; case '9' : result_low = 9; break; case 'A' : result_low = 10; break; case 'B' : result_low = 11; break; case 'C' : result_low = 12; break; case 'D' : result_low = 13; break; case 'E' : result_low = 14; break; case 'F' : result_low = 15; break; } return static_cast((result_high<<4) + result_low); } unsigned char* postgis_make_wkb_from_hex(char const* hexstr, size_t len) { assert(0 != hexstr); assert(0 == len % 2); // Decode hex stream to bin size_t wkbSize = len / 2; char two[2] = { 0 }; unsigned char* wkb = 0; wkb = new unsigned char[wkbSize]; size_t i = 0; size_t bi = 0; while (hexstr[i] != '\0' && i < len) { two[0] = hexstr[i++]; two[1] = hexstr[i++]; unsigned char uc = postgis_parse_hex(two); wkb[bi++] = uc; } assert(i == len); assert(bi == wkbSize); return wkb; } } // namespace fdoutility #endif // #ifndef FDOUTILITY_H_INCLUDED