Homebrew std::string for use with kernel I've ported some standard library facilities like vector, algorithm, etc. to my kernel so I can code in C++ instead of C. This is one of them. I'm looking for concerns regarding:


Performance
Safety
Friendly interface


Perhaps there are more idiomatic ways to accomplish what I'm going for?

#ifndef _LIBCPP_STRING_H_
#define _LIBCPP_STRING_H_

#include &lt;prefix.h&gt;
#include &lt;libc/stddef.h&gt;
#include &lt;libc/string.h&gt;
#include &lt;libc/stdint.h&gt;

#include "algorithm.h"

namespace std
{
    template&lt;size_t Size&gt;
    class fixed_string
    {
    public:
        static constexpr size_t npos = static_cast&lt;size_t&gt;(UINT32_MAX);

        fixed_string() :
            _length(0)
        {
            _buffer[0] = '\0';
        }
        fixed_string(const char *string)
        {
            assign(string, strlen(string));
        }
        fixed_string(const fixed_string &amp;other)
        {
            assign(other._buffer, other._length);
        }


        fixed_string &amp;operator =(const fixed_string &amp;other)
        {
            assign(other._buffer, other._length);
            return *this;
        }
        fixed_string &amp;operator =(const char *string)
        {
            assign(string, strlen(string));
            return *this;
        }


        bool operator ==(const fixed_string &amp;other) const
        {
            if(_length != other._length)
                return false;

            return (strcmp(other._buffer, _buffer) == 0);
        }
        bool operator ==(const char *string) const
        {
            return (strcmp(string, _buffer) == 0);
        }

        bool operator !=(const fixed_string &amp;other) const
        {
            return !(*this == other);
        }
        bool operator !=(const char *string) const
        {
            return !(*this == string);
        }


        size_t find(const fixed_string &amp;other) const
        {
            return find(other._buffer, _length);
        }
        size_t find(const char *other) const
        {
            return find(other, strlen(other));
        }
        size_t find(const char *other, size_t length) const
        {
            size_t found  = 0;

            char *buffer = _buffer;
            while(*buffer)
            {
                if(found &gt;= length)
                {
                    size_t diff = ((buffer - found) - _buffer);
                    return diff;
                }

                found = (*buffer == other[found]) ? found + 1 : 0;
                buffer ++;
            }

            return npos;
        }

        const char *c_str() const { return _buffer; }
        size_t length() const { return _length; }

    private:
        void assign(const char *string, size_t length)
        {
            if(!string)
            {
                _buffer[0] = '\0';
                _length = 0;

                return;
            }

            _length = std::min(length, Size);
            strlcpy(_buffer, string, _length);
        }

        char _buffer[Size + 1];
        size_t _length;
    };
}

#endif /* _LIBCPP_STRING_H_ */
In operator=(), you should always first check to see whether you're doing a self-assignment and do an early exit:

fixed_string &amp;operator =(const fixed_string &amp;other)
{
    if (this == &amp;other) {
        return *this;
    }
    assign(other._buffer, other._length);
    return *this;
}


I would write the found assignment as the more explicit:

if (*buffer == other[found]) {
    found++;
} else {
    found = 0;
}


The compiler will generate the equivalent code to yours.

In fact, your find has a bug. Consider:

fixed_string&lt;10&gt; a = "abcabcd";
assert(a.find("abcd") == 3);


Your assign method calls strlcpy incorrectly. Instead of calling with _length as the third parameter, use the actual size of the buffer:

strlcpy(_buffer, string, sizeof(_buffer));


As a matter of style, I would always surround conditional blocks with braces, even if they only contain one statement:

bool operator ==(const fixed_string &amp;other) const
{
    if(_length != other._length) {
        return false;
    }
    // ...