X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Fvisuals%2Fvisual-url.cpp;h=451ac06fdad8212328f03803588a4175added098;hp=b1f5f3e1939bb3d349eb9f2a2a4cb4cf4ee167ce;hb=HEAD;hpb=c20463e1d4a77117810c67adfec49bcdfab5efde diff --git a/dali-toolkit/internal/visuals/visual-url.cpp b/dali-toolkit/internal/visuals/visual-url.cpp index b1f5f3e..2f16427 100644 --- a/dali-toolkit/internal/visuals/visual-url.cpp +++ b/dali-toolkit/internal/visuals/visual-url.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2024 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,7 @@ #include // EXTERNAL HEADERS +#include #include // for toupper() namespace Dali @@ -26,107 +27,159 @@ namespace Toolkit { namespace Internal { - namespace { +constexpr uint32_t URL_ELLIPSED_LENGTH = 20u; + +static_assert(URL_ELLIPSED_LENGTH < URL_ELLIPSED_LENGTH + 3u); ///< Guard overflow cases. (for svace) -VisualUrl::ProtocolType ResolveLocation( const std::string& url ) +VisualUrl::ProtocolType ResolveLocation(const std::string& url) { - const char* urlCStr = url.c_str(); - const uint32_t length = url.size(); - if( ( length > 7 ) && urlCStr[5] == ':' && urlCStr[6] == '/' && urlCStr[7] == '/' ) + const char* urlCStr = url.c_str(); + const uint32_t length = url.size(); + if((length > 7) && urlCStr[5] == ':' && urlCStr[6] == '/' && urlCStr[7] == '/') { - // https:// - if( ( 'h' == tolower( urlCStr[0] ) )&& - ( 't' == tolower( urlCStr[1] ) )&& - ( 't' == tolower( urlCStr[2] ) )&& - ( 'p' == tolower( urlCStr[3] ) )&& - ( 's' == tolower( urlCStr[4] ) ) ) + // https:// or enbuf:// + const char hOre = tolower(urlCStr[0]); + const char tOrn = tolower(urlCStr[1]); + const char tOrb = tolower(urlCStr[2]); + const char pOru = tolower(urlCStr[3]); + const char sOrf = tolower(urlCStr[4]); + if(('h' == hOre) && + ('t' == tOrn) && + ('t' == tOrb) && + ('p' == pOru) && + ('s' == sOrf)) { return VisualUrl::REMOTE; } + if(('e' == hOre) && + ('n' == tOrn) && + ('b' == tOrb) && + ('u' == pOru) && + ('f' == sOrf)) + { + return VisualUrl::BUFFER; + } } - else if( ( length > 6 ) && urlCStr[4] == ':' && urlCStr[5] == '/' && urlCStr[6] == '/' ) + else if((length > 6) && urlCStr[4] == ':' && urlCStr[5] == '/' && urlCStr[6] == '/') { // http:// or dali:// - const char hOrd = tolower( urlCStr[0] ); - const char tOra = tolower( urlCStr[1] ); - const char tOrl = tolower( urlCStr[2] ); - const char pOri = tolower( urlCStr[3] ); - if( ( 'h' == hOrd )&& - ( 't' == tOra )&& - ( 't' == tOrl )&& - ( 'p' == pOri ) ) + const char hOrd = tolower(urlCStr[0]); + const char tOra = tolower(urlCStr[1]); + const char tOrl = tolower(urlCStr[2]); + const char pOri = tolower(urlCStr[3]); + if(('h' == hOrd) && + ('t' == tOra) && + ('t' == tOrl) && + ('p' == pOri)) { return VisualUrl::REMOTE; } - if( ( 'd' == hOrd )&& - ( 'a' == tOra )&& - ( 'l' == tOrl )&& - ( 'i' == pOri ) ) + if(('d' == hOrd) && + ('a' == tOra) && + ('l' == tOrl) && + ('i' == pOri)) { return VisualUrl::TEXTURE; } } - else if( ( length > 5 ) && urlCStr[3] == ':' && urlCStr[4] == '/' && urlCStr[5] == '/' ) + else if((length > 5) && urlCStr[3] == ':' && urlCStr[4] == '/' && urlCStr[5] == '/') { // ftp:// or ssh:// - const char fOrS = tolower( urlCStr[0] ); - if( ( 'f' == fOrS )||( 's' == fOrS ) ) + const char fOrs = tolower(urlCStr[0]); + const char tOrs = tolower(urlCStr[1]); + const char pOrh = tolower(urlCStr[2]); + if(('f' == fOrs) && + ('t' == tOrs) && + ('p' == pOrh)) { - const char tOrs = tolower( urlCStr[1] ); - if( ( 't' == tOrs )||( 's' == tOrs ) ) - { - const char pOrh = tolower( urlCStr[2] ); - if( ( 'p' == pOrh )||( 'h' == pOrh ) ) - { - return VisualUrl::REMOTE; - } - } + return VisualUrl::REMOTE; + } + if(('s' == fOrs) && + ('s' == tOrs) && + ('h' == pOrh)) + { + return VisualUrl::REMOTE; } } return VisualUrl::LOCAL; } - -VisualUrl::Type ResolveType( const std::string& url ) +VisualUrl::Type ResolveType(const std::string& url) { // if only one char in string, can only be regular image - const std::size_t count = url.size(); - if( count > 0 ) + const std::size_t count = url.size(); + VisualUrl::Type returnType = VisualUrl::REGULAR_IMAGE; + if(count > 0) { // parsing from the end for better chance of early outs - enum { SUFFIX, HASH, HASH_DOT } state = SUFFIX; - char SVG[ 4 ] = { 'g', 'v', 's', '.' }; - char GIF[ 4 ] = { 'f', 'i', 'g', '.' }; - unsigned int svgScore = 0; - unsigned int gifScore = 0; - int index = count; - while( --index >= 0 ) + enum { - const char currentChar = tolower( url[ index ] ); + SUFFIX, + HASH, + HASH_DOT + } state = SUFFIX; + char SVG[4] = {'g', 'v', 's', '.'}; + char GIF[4] = {'f', 'i', 'g', '.'}; + char WEBP[5] = {'p', 'b', 'e', 'w', '.'}; + char JSON[5] = {'n', 'o', 's', 'j', '.'}; + char TVG[4] = {'g', 'v', 't', '.'}; + unsigned int svgScore = 0; + unsigned int tvgScore = 0; + unsigned int gifScore = 0; + unsigned int webpScore = 0; + unsigned int jsonScore = 0; + int index = count; + while(--index >= 0) + { + const char currentChar = tolower(url[index]); const std::size_t offsetFromEnd = count - index - 1u; - if( ( offsetFromEnd < sizeof(SVG) )&&( currentChar == SVG[ offsetFromEnd ] ) ) + if((offsetFromEnd < sizeof(SVG)) && (currentChar == SVG[offsetFromEnd])) { // early out if SVG as can't be used in N patch for now - if( ++svgScore == sizeof(SVG) ) + if(++svgScore == sizeof(SVG)) { return VisualUrl::SVG; } } - if( ( offsetFromEnd < sizeof(GIF) )&&( currentChar == GIF[ offsetFromEnd ] ) ) + if((offsetFromEnd < sizeof(TVG)) && (currentChar == TVG[offsetFromEnd])) { - // early out if GIF as can't be used in N patch for now - if( ++gifScore == sizeof(GIF) ) + // early out if TVG as can't be used in N patch for now + if(++tvgScore == sizeof(TVG)) { - return VisualUrl::GIF; + return VisualUrl::TVG; } } - switch( state ) + if((offsetFromEnd < sizeof(GIF)) && (currentChar == GIF[offsetFromEnd])) + { + //find type, but need to be check used in N patch + if(++gifScore == sizeof(GIF)) + { + returnType = VisualUrl::GIF; + } + } + if((offsetFromEnd < sizeof(WEBP)) && (currentChar == WEBP[offsetFromEnd])) + { + if(++webpScore == sizeof(WEBP)) + { + //find type, but need to be check used in N patch + returnType = VisualUrl::WEBP; + } + } + if((offsetFromEnd < sizeof(JSON)) && (currentChar == JSON[offsetFromEnd])) + { + // early out if JSON as can't be used in N patch for now + if(++jsonScore == sizeof(JSON)) + { + return VisualUrl::JSON; + } + } + switch(state) { case SUFFIX: { - if( '.' == currentChar ) + if('.' == currentChar) { state = HASH; } @@ -134,27 +187,27 @@ VisualUrl::Type ResolveType( const std::string& url ) } case HASH: { - if( ( '#' == currentChar ) || ( '9' == currentChar ) ) + if(('#' == currentChar) || ('9' == currentChar)) { state = HASH_DOT; } else { // early out, not a valid N/9-patch URL - return VisualUrl::REGULAR_IMAGE; + return returnType; } break; } case HASH_DOT: { - if( '.' == currentChar ) + if('.' == currentChar) { return VisualUrl::N_PATCH; } else { // early out, not a valid N/9-patch URL - return VisualUrl::REGULAR_IMAGE; + return returnType; } break; } @@ -162,49 +215,79 @@ VisualUrl::Type ResolveType( const std::string& url ) } } // if we got here it is a regular image - return VisualUrl::REGULAR_IMAGE; -} - + return returnType; } +} // namespace VisualUrl::VisualUrl() : mUrl(), - mType( VisualUrl::REGULAR_IMAGE ), - mLocation( VisualUrl::LOCAL ) + mType(VisualUrl::REGULAR_IMAGE), + mLocation(VisualUrl::LOCAL), + mUrlHash(0ull) { } -VisualUrl::VisualUrl( const std::string& url ) -: mUrl( url ), - mType( VisualUrl::REGULAR_IMAGE ), - mLocation( VisualUrl::LOCAL ) +VisualUrl::VisualUrl(const std::string& url) +: mUrl(url), + mType(VisualUrl::REGULAR_IMAGE), + mLocation(VisualUrl::LOCAL), + mUrlHash(0ull) { - if( ! url.empty() ) + if(!url.empty()) { - mLocation = ResolveLocation( url ); - if( VisualUrl::TEXTURE != mLocation ) + mLocation = ResolveLocation(url); + if(VisualUrl::TEXTURE != mLocation) { // TEXTURE location url doesn't need type resolving, REGULAR_IMAGE is fine - mType = ResolveType( url ); + mType = ResolveType(url); } } } -VisualUrl::VisualUrl( const VisualUrl& url ) -: mUrl( url.mUrl ), - mType( url.mType ), - mLocation( url.mLocation ) +VisualUrl::VisualUrl(const VisualUrl& url) +: mUrl(url.mUrl), + mType(url.mType), + mLocation(url.mLocation), + mUrlHash(url.mUrlHash) { } -VisualUrl& VisualUrl::operator=( const VisualUrl& url ) +VisualUrl::VisualUrl(VisualUrl&& url) noexcept +: mUrl(std::move(url.mUrl)), + mType(std::move(url.mType)), + mLocation(std::move(url.mLocation)), + mUrlHash(std::move(url.mUrlHash)) { - if( &url != this ) + url.mUrlHash = 0ull; +} + +VisualUrl::~VisualUrl() +{ +} + +VisualUrl& VisualUrl::operator=(const VisualUrl& url) +{ + if(&url != this) { - mUrl = url.mUrl; - mType = url.mType; + mUrl = url.mUrl; + mType = url.mType; mLocation = url.mLocation; + mUrlHash = url.mUrlHash; + } + return *this; +} + +VisualUrl& VisualUrl::operator=(VisualUrl&& url) noexcept +{ + if(&url != this) + { + mUrl = std::move(url.mUrl); + mType = std::move(url.mType); + mLocation = std::move(url.mLocation); + mUrlHash = std::move(url.mUrlHash); + + url.mUrlHash = 0ull; } return *this; } @@ -214,6 +297,22 @@ const std::string& VisualUrl::GetUrl() const return mUrl; } +std::string VisualUrl::GetEllipsedUrl() const +{ + if(mUrl.size() > URL_ELLIPSED_LENGTH + 3) + { + std::string ellipsedUrl = "..."; + ellipsedUrl += mUrl.substr(mUrl.size() - URL_ELLIPSED_LENGTH); + return ellipsedUrl; + } + return mUrl; +} + +std::uint64_t VisualUrl::GetUrlHash() const +{ + return DALI_UNLIKELY(mUrlHash == 0) ? (mUrlHash = Dali::CalculateHash(mUrl)) : mUrlHash; +} + VisualUrl::Type VisualUrl::GetType() const { return mType; @@ -234,23 +333,60 @@ bool VisualUrl::IsLocalResource() const return mLocation == VisualUrl::LOCAL; } +bool VisualUrl::IsBufferResource() const +{ + return mLocation == VisualUrl::BUFFER; +} + std::string VisualUrl::GetLocation() const { - const auto location = mUrl.find( "://" ); - if( std::string::npos != location ) + return GetLocation(mUrl); +} + +std::string VisualUrl::GetLocationWithoutExtension() const +{ + return GetLocationWithoutExtension(mUrl); +} + +std::string VisualUrl::CreateTextureUrl(const std::string& location) +{ + return "dali://" + location; +} + +std::string VisualUrl::CreateBufferUrl(const std::string& location, const std::string_view& extension) +{ + return "enbuf://" + location + std::string(extension); +} + +VisualUrl::ProtocolType VisualUrl::GetProtocolType(const std::string& url) +{ + return ResolveLocation(url); +} + +std::string VisualUrl::GetLocation(const std::string& url) +{ + const auto location = url.find("://"); + if(std::string::npos != location) { - return mUrl.substr( location + 3u ); // 3 characters forwards from the start of :// + return url.substr(location + 3u); // 3 characters forwards from the start of :// } - return mUrl; + return url; } -std::string VisualUrl::CreateTextureUrl( const std::string& location ) +std::string VisualUrl::GetLocationWithoutExtension(const std::string& url) { - return "dali://" + location; + const auto location = url.find("://"); + if(std::string::npos != location) + { + const auto extension = url.find_last_of("."); // Find last position of '.' keyword. + const auto locationLength = extension != std::string::npos ? extension - (location + 3u) : std::string::npos; + return url.substr(location + 3u, locationLength); // 3 characters forwards from the start of ://, and end of last '.' keyword. + } + return url; } -} // Internal +} // namespace Internal -} // Toolkit +} // namespace Toolkit -} // Dali +} // namespace Dali