3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-07-15 19:45:41 +00:00
z3/src/util/zstring.h
Clemens Eisenhofer 596cc14e83 Replaced stabilizers by landing decomposition (faster!)
Rank membership constraints by estimated size of their automaton
Some refactoring
Some bug fixes
2026-07-09 23:24:11 +02:00

165 lines
5.4 KiB
C++

/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
zstring.h
Abstract:
String wrapper for unicode/ascii internal strings as vectors
Author:
Nikolaj Bjorner (nbjorner) 2021-01-26
--*/
#pragma once
#include <cstdint>
#include <string>
#include "util/buffer.h"
#include "util/rational.h"
#include "util/vector.h"
enum class string_encoding {
ascii, // exactly 8 bits
unicode,
bmp // basic multilingual plane; exactly 16 bits
};
class zstring {
private:
buffer<uint32_t> m_buffer;
bool well_formed() const;
bool is_escape_char(char const *& s, unsigned& result);
public:
static unsigned unicode_max_char() { return 196607; }
static unsigned unicode_num_bits() { return 18; }
static unsigned bmp_max_char() { return 65535; }
static unsigned bmp_num_bits() { return 16; }
static unsigned ascii_max_char() { return 255; }
static unsigned ascii_num_bits() { return 8; }
static unsigned max_char() {
switch (get_encoding()) {
case string_encoding::unicode:
return unicode_max_char();
case string_encoding::bmp:
return bmp_max_char();
case string_encoding::ascii:
return ascii_max_char();
}
return unicode_max_char();
}
static unsigned num_bits() {
switch (get_encoding()) {
case string_encoding::unicode:
return unicode_num_bits();
case string_encoding::bmp:
return bmp_num_bits();
case string_encoding::ascii:
return ascii_num_bits();
}
return unicode_num_bits();
}
static string_encoding get_encoding();
zstring() = default;
zstring(char const* s);
zstring(const std::string &str) : zstring(str.c_str()) {}
zstring(rational const& r): zstring(r.to_string()) {}
zstring(unsigned sz, unsigned const* s) { m_buffer.append(sz, s); SASSERT(well_formed()); }
zstring(unsigned ch);
zstring replace(zstring const& src, zstring const& dst) const;
zstring reverse() const;
std::string encode() const;
unsigned length() const { return m_buffer.size(); }
unsigned operator[](unsigned i) const { return m_buffer[i]; }
bool empty() const { return m_buffer.empty(); }
bool suffixof(zstring const& other) const;
bool prefixof(zstring const& other) const;
bool contains(zstring const& other) const;
int indexofu(zstring const& other, unsigned offset) const;
int last_indexof(zstring const& other) const;
zstring extract(unsigned offset, unsigned length) const;
zstring operator+(zstring const& other) const;
bool operator==(const zstring& other) const;
bool operator!=(const zstring& other) const;
unsigned hash() const;
void reset() { m_buffer.reset(); }
zstring& operator+=(zstring const& other) { m_buffer.append(other.m_buffer); return *this; }
uint32_t const* begin() const { return m_buffer.begin(); }
uint32_t const* end() const { return m_buffer.end(); }
friend std::ostream& operator<<(std::ostream &os, const zstring &str);
friend bool operator<(const zstring& lhs, const zstring& rhs);
};
// half-open character interval [lo, hi)
struct char_range {
unsigned m_lo;
unsigned m_hi; // exclusive
char_range(): m_lo(0), m_hi(0) {}
char_range(unsigned c): m_lo(c), m_hi(c + 1) {}
char_range(unsigned lo, unsigned hi): m_lo(lo), m_hi(hi) { SASSERT(lo <= hi); }
bool is_empty() const { return m_lo == m_hi; }
bool is_unit() const { return m_hi == m_lo + 1; }
unsigned length() const { return m_hi - m_lo; }
bool contains(unsigned c) const { return c >= m_lo && c < m_hi; }
bool operator==(char_range const& o) const { return m_lo == o.m_lo && m_hi == o.m_hi; }
bool operator<(char_range const& o) const {
return m_lo < o.m_lo || (m_lo == o.m_lo && m_hi < o.m_hi);
}
};
// sorted list of non-overlapping character intervals
class char_set {
svector<char_range> m_ranges;
public:
char_set() = default;
explicit char_set(char_range const& r) { if (!r.is_empty()) m_ranges.push_back(r); }
static char_set full(unsigned max_char) { return char_set(char_range(0, max_char + 1)); }
bool is_empty() const { return m_ranges.empty(); }
bool is_full(unsigned max_char) const {
return m_ranges.size() == 1 && m_ranges[0].m_lo == 0 && m_ranges[0].m_hi == max_char + 1;
}
bool is_unit() const { return m_ranges.size() == 1 && m_ranges[0].is_unit(); }
unsigned first_char() const { SASSERT(!is_empty()); return m_ranges[0].m_lo; }
svector<char_range> const& ranges() const { return m_ranges; }
// total number of characters in the set
unsigned char_count() const;
// membership test via binary search
bool contains(unsigned c) const;
// add a single character
void add(unsigned c);
// union with another char_set
void add(char_set const& other);
// intersect with another char_set, returns the result
char_set intersect_with(char_set const& other) const;
// complement relative to [0, max_char]
char_set complement(unsigned max_char) const;
// check if two sets are disjoint
bool is_disjoint(char_set const& other) const;
// check if this set is a subset of other (every char in this is also in other)
bool is_subset(char_set const& other) const;
bool operator==(char_set const& other) const { return m_ranges == other.m_ranges; }
char_set clone() const { char_set r; r.m_ranges = m_ranges; return r; }
std::ostream& display(std::ostream& out) const;
};