Current Version: 1.0.33
Project Name: csspp
unicode_range.cpp
Go to the documentation of this file.
1// Copyright (c) 2015-2025 Made to Order Software Corp. All Rights Reserved
2//
3// This program is free software; you can redistribute it and/or modify
4// it under the terms of the GNU General Public License as published by
5// the Free Software Foundation; either version 2 of the License, or
6// (at your option) any later version.
7//
8// This program is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11// GNU General Public License for more details.
12//
13// You should have received a copy of the GNU General Public License along
14// with this program; if not, write to the Free Software Foundation, Inc.,
15// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16
17#include "csspp/unicode_range.h"
18
19#include "csspp/exception.h"
20
21#include <iomanip>
22#include <iostream>
23#include <sstream>
24
25namespace csspp
26{
27
28namespace
29{
30
32{
33 return range & 0xFFFFFFFFLL;
34}
35
37{
38 return (range >> 32) & 0xFFFFFFFFLL;
39}
40
42{
43 return (static_cast<range_value_t>(end) << 32) | static_cast<range_value_t>(start);
44}
45
46void verify_range(range_value_t const range)
47{
48 // verify maximum
49 wide_char_t const start(range_to_start(range));
50 if(start >= 0x110000)
51 {
52 std::stringstream ss;
53 ss << "the start parameter is limited to a maximum of 0x10FFFF, it is 0x" << std::hex << start << " now.";
54 throw csspp_exception_overflow(ss.str());
55 }
56
57 // verify minimum
58 wide_char_t const end(range_to_end(range));
59 if(end >= 0x200000) // special end to support all possible masks
60 {
61 std::stringstream ss;
62 ss << "the end parameter is limited to a maximum of 0x1FFFFF, it is 0x" << std::hex << end << " now.";
63 throw csspp_exception_overflow(ss.str());
64 }
65
66 // must always be properly ordered
67 if(start > end)
68 {
69 std::stringstream ss;
70 ss << "the start parameter (" << std::hex << start << ") cannot be larged than the end parameter (" << end << ") in a unicode range.";
71 throw csspp_exception_overflow(ss.str());
72 }
73}
74
75} // no name namespace
76
78 : f_range(range)
79{
80 verify_range(f_range);
81}
82
84 : f_range(start_end_to_range(start, end))
85{
86 verify_range(f_range);
87}
88
90{
91 verify_range(range);
92 f_range = range;
93}
94
96{
97 range_value_t const range(start_end_to_range(start, end));
98 verify_range(range);
99 f_range = range;
100}
101
106
108{
109 return range_to_start(f_range);
110}
111
113{
114 return range_to_end(f_range);
115}
116
117std::string unicode_range_t::to_string() const
118{
119 wide_char_t start(range_to_start(f_range));
120 wide_char_t end(range_to_end(f_range));
121
122 // a special case for the 6 x '?' mask
123 if(start == 0 && end >= 0x10FFFF)
124 {
125 return "??????";
126 }
127
128 std::stringstream ss;
129 ss << std::hex << start;
130
131 // if start and end are equal
132 if(start == end)
133 {
134 // if equal, we return that one number
135 return ss.str();
136 }
137
138 // check whether we can use the question mark trick
139 {
140 std::stringstream filled;
141 filled << std::hex << std::setw(6) << std::setfill('0') << start;
142 std::string const start_str(filled.str());
143 filled.str("");
144 filled << std::setw(6) << end;
145 std::string const end_str(filled.str());
146 if(start_str.length() != 6 || end_str.length() != 6)
147 {
148 throw csspp_exception_logic("unexpected string length"); // LCOV_EXCL_LINE
149 }
150 size_t p(6);
151 for(; p > 0; --p)
152 {
153 if(start_str[p - 1] != '0' || end_str[p - 1] != 'f')
154 {
155 break;
156 }
157 }
158 std::string result(start_str.substr(0, p));
159 if(result == end_str.substr(0, p))
160 {
161 // we can use a plain ??? mask
162 result += std::string("??????", 6 - p);
163 // remove leading zeroes
164 while(result.front() == '0')
165 {
166 result.erase(result.begin());
167 }
168 return result;
169 }
170 }
171
172 // no question mark, just append the end
173 ss << "-" << end;
174
175 return ss.str();
176}
177
178} // namespace csspp
179
180// Local Variables:
181// mode: cpp
182// indent-tabs-mode: nil
183// c-basic-offset: 4
184// tab-width: 4
185// End:
186
187// vim: ts=4 sw=4 et
wide_char_t get_end() const
wide_char_t get_start() const
range_value_t get_range() const
void set_range(range_value_t range)
std::string to_string() const
unicode_range_t(range_value_t value=0)
wide_char_t constexpr range_to_start(range_value_t const range)
void verify_range(range_value_t const range)
wide_char_t constexpr range_to_end(range_value_t const range)
range_value_t constexpr start_end_to_range(wide_char_t start, wide_char_t end)
The namespace of all the classes in the CSS Preprocessor.
Definition csspp.h:48
uint64_t range_value_t
int32_t wide_char_t
Definition csspp.h:55

Documentation of CSS Preprocessor.

This document is part of the Snap! Websites Project.

Copyright by Made to Order Software Corp.