Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright 2016 Wladimir J. van der Laan2// Distributed under the MIT software license, see the accompanying3// file COPYING or https://opensource.org/licenses/mit-license.php.4#ifndef BITCOIN_UNIVALUE_INCLUDE_UNIVALUE_UTFFILTER_H5#define BITCOIN_UNIVALUE_INCLUDE_UNIVALUE_UTFFILTER_H7#include <string>9/**10* Filter that generates and validates UTF-8, as well as collates UTF-1611* surrogate pairs as specified in RFC4627.12*/13class JSONUTF8StringFilter14{15public:16explicit JSONUTF8StringFilter(std::string& s)17: str(s)18{19}20// Write single 8-bit char (may be part of UTF-8 sequence)21void push_back(unsigned char ch)22{23if (state == 0) {24if (ch < 0x80) // 7-bit ASCII, fast direct pass-through25str.push_back(ch);26else if (ch < 0xc0) // Mid-sequence character, invalid in this state27is_valid = false;28else if (ch < 0xe0) { // Start of 2-byte sequence29codepoint = (ch & 0x1f) << 6;30state = 6;31} else if (ch < 0xf0) { // Start of 3-byte sequence32codepoint = (ch & 0x0f) << 12;33state = 12;34} else if (ch < 0xf8) { // Start of 4-byte sequence35codepoint = (ch & 0x07) << 18;36state = 18;37} else // Reserved, invalid38is_valid = false;39} else {40if ((ch & 0xc0) != 0x80) // Not a continuation, invalid41is_valid = false;42state -= 6;43codepoint |= (ch & 0x3f) << state;44if (state == 0)45push_back_u(codepoint);46}47}48// Write codepoint directly, possibly collating surrogate pairs49void push_back_u(unsigned int codepoint_)50{51if (state) // Only accept full codepoints in open state52is_valid = false;53if (codepoint_ >= 0xD800 && codepoint_ < 0xDC00) { // First half of surrogate pair54if (surpair) // Two subsequent surrogate pair openers - fail55is_valid = false;56else57surpair = codepoint_;58} else if (codepoint_ >= 0xDC00 && codepoint_ < 0xE000) { // Second half of surrogate pair59if (surpair) { // Open surrogate pair, expect second half60// Compute code point from UTF-16 surrogate pair61append_codepoint(0x10000 | ((surpair - 0xD800)<<10) | (codepoint_ - 0xDC00));62surpair = 0;63} else // Second half doesn't follow a first half - fail64is_valid = false;65} else {66if (surpair) // First half of surrogate pair not followed by second - fail67is_valid = false;68else69append_codepoint(codepoint_);70}71}72// Check that we're in a state where the string can be ended73// No open sequences, no open surrogate pairs, etc74bool finalize()75{76if (state || surpair)77is_valid = false;78return is_valid;79}80private:81std::string &str;82bool is_valid{true};83// Current UTF-8 decoding state84unsigned int codepoint{0};85int state{0}; // Top bit to be filled in for next UTF-8 byte, or 087// Keep track of the following state to handle the following section of88// RFC4627:89//90// To escape an extended character that is not in the Basic Multilingual91// Plane, the character is represented as a twelve-character sequence,92// encoding the UTF-16 surrogate pair. So, for example, a string93// containing only the G clef character (U+1D11E) may be represented as94// "\uD834\uDD1E".95//96// Two subsequent \u.... may have to be replaced with one actual codepoint.97unsigned int surpair{0}; // First half of open UTF-16 surrogate pair, or 099void append_codepoint(unsigned int codepoint_)100{101if (codepoint_ <= 0x7f)102str.push_back((char)codepoint_);103else if (codepoint_ <= 0x7FF) {104str.push_back((char)(0xC0 | (codepoint_ >> 6)));105str.push_back((char)(0x80 | (codepoint_ & 0x3F)));106} else if (codepoint_ <= 0xFFFF) {107str.push_back((char)(0xE0 | (codepoint_ >> 12)));108str.push_back((char)(0x80 | ((codepoint_ >> 6) & 0x3F)));109str.push_back((char)(0x80 | (codepoint_ & 0x3F)));110} else if (codepoint_ <= 0x1FFFFF) {111str.push_back((char)(0xF0 | (codepoint_ >> 18)));112str.push_back((char)(0x80 | ((codepoint_ >> 12) & 0x3F)));113str.push_back((char)(0x80 | ((codepoint_ >> 6) & 0x3F)));114str.push_back((char)(0x80 | (codepoint_ & 0x3F)));115}116}117};119#endif // BITCOIN_UNIVALUE_INCLUDE_UNIVALUE_UTFFILTER_H
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.