#include <string>
#include <algorithm>
#include <ostream>
class taille_illegale {};
class indice_invalide {};
class petite_chaine {
enum { MAX = 255 };
char txt_[MAX + 1] {};
template <class T>
static bool est_taille_valide(T val) { // ici: spécialiser pour T unsigned? valider T integral?
return 0 <= val && val <= MAX;
}
// précondition: est_taille_valide(val)
void taille(unsigned char val) {
*reinterpret_cast<unsigned char*>(&txt_[0]) = val;
}
public:
using size_type = std::size_t; // suggestion
petite_chaine() = default;
petite_chaine(const std::string &s) {
using namespace std;
if (!est_taille_valide(s.size()))
throw taille_illegale{};
copy(begin(s), end(s), &txt_[1]);
taille(s.size());
}
// précondition: p == nullptr || p est valide
petite_chaine(const char *p) {
if (!p)
taille(0);
else {
size_type n = 0;
for (; *p && n <= MAX; ++n, ++p)
txt_[n + 1] = *p;
if (*p)
throw taille_illegale{};
taille(n);
}
}
size_type size() const {
return *reinterpret_cast<const unsigned char*>(&txt_[0]);
}
bool empty() const {
return size() == 0;
}
bool operator==(const petite_chaine &autre) const {
return size() == autre.size() && std::equal(&txt_[1], &txt_[size()], &autre.txt_[1]);
}
bool operator!=(const petite_chaine &autre) const {
return !(*this == autre);
}
bool operator < (const petite_chaine &autre) const {
return std::lexicographical_compare(&txt_[1], &txt_[size()], &autre.txt_[1], &autre.txt_[autre.size()]);
}
bool operator <= (const petite_chaine &autre) const {
return !(autre < *this);
}
bool operator > (const petite_chaine &autre) const {
return autre < *this;
}
bool operator >= (const petite_chaine &autre) const {
return !(*this < autre);
}
friend std::ostream& operator<<(std::ostream &os, const petite_chaine &s) {
for(auto i = &s.txt_[1]; i != &s.txt_[s.size()]; ++i)
os << *i;
return os;
}
char& operator[](size_type n) {
// if (n >= size()) throw indice_invalide{};
return txt_[n + 1];
}
char operator[](size_type n) const {
// if (n >= size()) throw indice_invalide{};
return txt_[n + 1];
}
};