Listing 1: fixed_char_buf.h — Header for the fixed-size string implementation

// Copyright (c) 2001 John Panzer
// Permission is granted to use this code without restriction as
// long as this copyright notice appears in all source files.
#ifndef FIXED_CHAR_BUF_H_INCLUDED
#define FIXED_CHAR_BUF_H_INCLUDED

#include <string> // For char_traits
#include "xs_defs.h" // Utility macros

XS_NAMESPACE(xstr)

// Fixed size character buffer class.
template <size_t SIZE, 
          class CharT = char, 
          class Traits = std::char_traits<CharT> > 
class fixed_char_buf {
public: 
    // STL container interface typedefs:
    typedef CharT value_type;
    typedef value_type* pointer;
    typedef const value_type* const_pointer;
    typedef value_type& reference;
    typedef const value_type& const_reference;
    typedef size_t size_type;
    typedef ptrdiff_t difference_type;
    typedef const value_type* const_iterator;
    typedef value_type* iterator;
    typedef std::reverse_iterator<const_iterator> 
            const_reverse_iterator;
    typedef std::reverse_iterator<iterator> reverse_iterator; 
    typedef std::allocator<CharT> allocator_type;

    // String interface typedefs:
    typedef Traits traits_type;
    static const size_type npos;

    // Constructors:
    fixed_char_buf(allocator_type const &a=_allocator) {
        _end = _buffer;
    }

    fixed_char_buf(fixed_char_buf const &s) {
        range_initialize(s.begin(), s.end());
    }

    // Copy operator:
    fixed_char_buf &operator=(fixed_char_buf const &s) {
        if (this!=&s)
            range_initialize(s.begin(), s.end());
    }

    // Insert:
    template <class InputIter>
    void insert(iterator pos, InputIter first, InputIter last) {
        if (first!=last) { 
            size_type xtra = std::distance(first,last);
            if (pos != _end) {
                if (_end-_buffer + xtra >= SIZE)
                    throw std::out_of_range("fixed_char_buf"); 
                Traits::move(pos+xtra,pos,_end-pos);
            }
            std::copy(first,last,pos);
            _end += xtra; // Expand end point
        }
    }

    // Erase:
    iterator erase(iterator first, iterator last) {
        if (first != last) {
          Traits::move(first, last, (_end - last) + 1);
          const iterator new_finish = _end - (last - first);
          _end = new_finish;
        }
        return first;        
    }


    // STL container member function interface:
    const allocator_type &get_allocator() const {
        return _allocator;
    }
    
    iterator begin() {return _buffer;}
    const_iterator begin() const {return _buffer;}
    iterator end() {return _end;}
    const_iterator end() const {return _end;}

    void clear() {_end = _buffer;}
    size_t max_size() const { return SIZE; }
    bool empty() const { return (_end == _buffer); }    
    size_type size() const {return _end - _buffer;}

    void swap(fixed_char_buf& s) {
        for(int i=0;i<SIZE;++i) {
            std::swap(_buffer[i],s._buffer[i]);
        }
        int len = _end - _buffer;
        _end = s.size()+_buffer;
        s._end = len+s._buffer;
    }

    // String interface member functions:
    void reserve(size_type n = 0) {
        if (n > SIZE) 
            throw std::length_error("fixed_char_buf");
    } 
    size_type capacity() const { return max_size(); }

    const CharT* c_str() const {
        *_end = CharT(); // Null terminate.
        return _buffer;
    }

    const CharT* data() const {
        return _buffer;
    }

protected: 
    // Internal interface used by xstring wrapper.

    // Initializes with n copies of given element:
    void element_initialize(size_type n, value_type c) {
        if (n > SIZE) 
            throw std::length_error("fixed_char_buf");
        std::uninitialized_fill_n(begin(), n, c);
        _end = _buffer+n;
    }  

    // Initializes with given range of elements:
    template <class InputIter>
    void range_initialize(InputIter first, InputIter last) {
        size_t n = std::distance(first,last);
        if (n >= SIZE)
            throw std::length_error("fixed_char_buf");
        std::uninitialized_copy(first,last,_buffer);
        _end = _buffer+n; 
    }

private: 
    // A fixed size buffer implementation:
    CharT _buffer[SIZE+1]; // Space for SIZE elements + null 
    mutable CharT *_end ;  // End of text in _buffer
    static const allocator_type _allocator; // Dummy constant
};

template <size_t SIZE, class CharT, class Traits>
const fixed_char_buf<SIZE,CharT,Traits>::size_type 
      fixed_char_buf<SIZE,CharT,Traits>::npos 
      = (fixed_char_buf<SIZE,CharT,Traits>::size_type) -1;

template <size_t SIZE, class CharT, class Traits>
const fixed_char_buf<SIZE,CharT,Traits>::allocator_type 
      fixed_char_buf<SIZE,CharT,Traits>::_allocator;

XS_END_NAMESPACE

#endif
— End of Listing —