mirror of
https://github.com/catchorg/Catch2.git
synced 2025-09-19 03:15:40 +02:00
First cut of new, non-owning, StringRef class, with no dependencies in header
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
#pragma clang diagnostic ignored "-Wweak-vtables"
|
||||
#endif
|
||||
|
||||
#include "catch_stringref.hpp"
|
||||
#include "../catch_session.hpp"
|
||||
#include "catch_registry_hub.hpp"
|
||||
#include "catch_notimplemented_exception.hpp"
|
||||
|
82
include/internal/catch_stringref.h
Normal file
82
include/internal/catch_stringref.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 2016 Two Blue Cubes Ltd. All rights reserved.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifndef TWOBLUECUBES_CATCH_STRINGREF_H_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_STRINGREF_H_INCLUDED
|
||||
|
||||
#include "internal/catch_suppress_warnings.h"
|
||||
|
||||
namespace Catch {
|
||||
|
||||
// A non-owning string class (similar to the forthcoming std::string_view)
|
||||
// Note that, because a StringRef may be a substring of another string,
|
||||
// it may not be null terminated. c_str() must return a null terminated
|
||||
// string, however, and so the StringRef will internally take ownership
|
||||
// (taking a copy), if necessary. This internal mutable is not externally
|
||||
// visible - but does mean StringRefs should not be shared between
|
||||
// threads.
|
||||
class StringRef {
|
||||
protected:
|
||||
enum class Ownership {
|
||||
FullStringRef,
|
||||
SubStringRef,
|
||||
FullStringOwned
|
||||
};
|
||||
|
||||
using size_type = unsigned long;
|
||||
|
||||
char const* m_data;
|
||||
size_type m_size;
|
||||
Ownership m_ownership;
|
||||
|
||||
static StringRef s_emptyStringRef;
|
||||
|
||||
void takeOwnership();
|
||||
void deleteIfOwned();
|
||||
|
||||
// Access for testing purposes only ////////////
|
||||
friend auto rawCharData( StringRef const& stringRef ) -> char const*;
|
||||
friend auto isOwned( StringRef const& stringRef ) -> bool;
|
||||
friend auto isSubstring( StringRef const& stringRef ) -> bool;
|
||||
////////////////////////////////////////////////
|
||||
|
||||
public: // construction/ assignment
|
||||
StringRef();
|
||||
StringRef( StringRef const& other );
|
||||
StringRef( StringRef&& other );
|
||||
StringRef( char const* rawChars );
|
||||
StringRef( char const* rawChars, size_type size );
|
||||
~StringRef();
|
||||
|
||||
auto operator = ( StringRef const& other ) -> StringRef&;
|
||||
auto operator = ( StringRef&& other ) -> StringRef&;
|
||||
|
||||
public: // operators
|
||||
auto operator == ( StringRef const& other ) const -> bool;
|
||||
auto operator != ( StringRef const& other ) const -> bool;
|
||||
|
||||
auto operator[] ( size_type index ) const -> char {
|
||||
return m_data[index];
|
||||
}
|
||||
|
||||
public: // named queries
|
||||
auto empty() const -> bool {
|
||||
return m_size == 0;
|
||||
}
|
||||
auto size() const -> size_type {
|
||||
return m_size;
|
||||
}
|
||||
auto c_str() const -> char const*;
|
||||
|
||||
public: // substrings and searches
|
||||
auto substr( size_type start, size_type size ) const -> StringRef;
|
||||
};
|
||||
|
||||
} // namespace Catch
|
||||
|
||||
#include "internal/catch_reenable_warnings.h"
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_STRINGREF_H_INCLUDED
|
112
include/internal/catch_stringref.hpp
Normal file
112
include/internal/catch_stringref.hpp
Normal file
@@ -0,0 +1,112 @@
|
||||
#include "catch_stringref.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
StringRef StringRef::s_emptyStringRef = "";
|
||||
|
||||
StringRef::StringRef()
|
||||
: StringRef( s_emptyStringRef )
|
||||
{}
|
||||
|
||||
StringRef::StringRef( StringRef const& other )
|
||||
: m_data( other.m_data ),
|
||||
m_size( other.m_size ),
|
||||
m_ownership( other.m_ownership )
|
||||
{
|
||||
if( m_ownership == Ownership::FullStringOwned )
|
||||
m_ownership = Ownership::FullStringRef;
|
||||
}
|
||||
|
||||
StringRef::StringRef( StringRef&& other )
|
||||
: m_data( other.m_data ),
|
||||
m_size( other.m_size ),
|
||||
m_ownership( other.m_ownership )
|
||||
{
|
||||
if( m_ownership == Ownership::FullStringOwned )
|
||||
other.m_ownership = Ownership::FullStringRef;
|
||||
}
|
||||
|
||||
StringRef::StringRef( char const* rawChars )
|
||||
: m_data( rawChars ),
|
||||
m_size( std::strlen( rawChars ) ),
|
||||
m_ownership( Ownership::FullStringRef )
|
||||
{}
|
||||
StringRef::StringRef( char const* rawChars, size_type size )
|
||||
: m_data( rawChars ),
|
||||
m_size( size ),
|
||||
m_ownership( Ownership::SubStringRef )
|
||||
{
|
||||
size_type rawSize = std::strlen( rawChars );
|
||||
if( rawSize < size )
|
||||
size = rawSize;
|
||||
if( rawSize == size )
|
||||
m_ownership = Ownership::FullStringRef;
|
||||
}
|
||||
|
||||
StringRef::~StringRef() {
|
||||
deleteIfOwned();
|
||||
}
|
||||
|
||||
void StringRef::deleteIfOwned() {
|
||||
if( m_ownership == Ownership::FullStringOwned )
|
||||
delete m_data;
|
||||
}
|
||||
|
||||
auto StringRef::operator = ( StringRef const& other ) -> StringRef& {
|
||||
if( &other == this )
|
||||
return *this;
|
||||
deleteIfOwned();
|
||||
m_data = other.m_data;
|
||||
m_size = other.m_size;
|
||||
if( other.m_ownership == Ownership::FullStringOwned )
|
||||
m_ownership = Ownership::FullStringRef;
|
||||
else
|
||||
m_ownership = other.m_ownership;
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto StringRef::operator = ( StringRef&& other ) -> StringRef& {
|
||||
if( &other == this )
|
||||
return *this;
|
||||
deleteIfOwned();
|
||||
m_data = other.m_data;
|
||||
m_size = other.m_size;
|
||||
m_ownership = other.m_ownership;
|
||||
if( other.m_ownership == Ownership::FullStringOwned )
|
||||
other.m_ownership = Ownership::FullStringRef;
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto StringRef::c_str() const -> char const* {
|
||||
if( m_ownership == Ownership::SubStringRef )
|
||||
const_cast<StringRef*>( this )->takeOwnership();
|
||||
return m_data;
|
||||
}
|
||||
|
||||
void StringRef::takeOwnership() {
|
||||
if( m_ownership != Ownership::FullStringOwned ) {
|
||||
char* data = new char[m_size+1];
|
||||
std::memcpy( data, m_data, m_size );
|
||||
data[m_size] = '\0';
|
||||
m_data = data;
|
||||
m_ownership = Ownership::FullStringOwned;
|
||||
}
|
||||
}
|
||||
auto StringRef::substr( size_type start, size_type size ) const -> StringRef {
|
||||
if( start < m_size )
|
||||
return StringRef( m_data+start, size );
|
||||
else
|
||||
return StringRef();
|
||||
}
|
||||
auto StringRef::operator == ( StringRef const& other ) const -> bool {
|
||||
return size() == other.size() &&
|
||||
(std::strncmp( m_data, other.m_data, size() ) == 0);
|
||||
}
|
||||
auto StringRef::operator != ( StringRef const& other ) const -> bool {
|
||||
return !operator==( other );
|
||||
}
|
||||
|
||||
|
||||
} // namespace Catch
|
Reference in New Issue
Block a user