diff options
| author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2016-09-11 10:12:48 +0200 | 
|---|---|---|
| committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2016-09-11 10:12:48 +0200 | 
| commit | e09e4d5b8972ece3836162e24c229b7b0dc8c54d (patch) | |
| tree | 6d14f5c04411d53c26c9dd7be71d2dcbaac2abd4 /src | |
| parent | 92ed3202e425b59cf0008f054fef133ba9cccc32 (diff) | |
| download | ODR-AudioEnc-e09e4d5b8972ece3836162e24c229b7b0dc8c54d.tar.gz ODR-AudioEnc-e09e4d5b8972ece3836162e24c229b7b0dc8c54d.tar.bz2 ODR-AudioEnc-e09e4d5b8972ece3836162e24c229b7b0dc8c54d.zip | |
Remove mot-encoder
Diffstat (limited to 'src')
| -rw-r--r-- | src/charset-test.cpp | 57 | ||||
| -rw-r--r-- | src/charset.h | 115 | ||||
| -rw-r--r-- | src/mot-encoder.cpp | 1831 | ||||
| -rw-r--r-- | src/utf8.h | 34 | ||||
| -rw-r--r-- | src/utf8/checked.h | 327 | ||||
| -rw-r--r-- | src/utf8/core.h | 329 | ||||
| -rw-r--r-- | src/utf8/unchecked.h | 228 | 
7 files changed, 0 insertions, 2921 deletions
| diff --git a/src/charset-test.cpp b/src/charset-test.cpp deleted file mode 100644 index d65fcc7..0000000 --- a/src/charset-test.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* -    Copyright (C) 2015 Matthias P. Braendli (http://opendigitalradio.org) - -    This program is free software: you can redistribute it and/or modify -    it under the terms of the GNU General Public License as published by -    the Free Software Foundation, either version 3 of the License, or -    (at your option) any later version. - -    This program is distributed in the hope that it will be useful, -    but WITHOUT ANY WARRANTY; without even the implied warranty of -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -    GNU General Public License for more details. - -    You should have received a copy of the GNU General Public License -    along with this program.  If not, see <http://www.gnu.org/licenses/>. - -    charset.cpp -         This is test code for the character set conversion. It does not -         get compiled by default. -         Please use -         g++ -Wall -Wextra -std=c++11 -o charset-test charset-test.cpp -         to compile this, and create a input.txt file with test data. - -    Authors: -         Matthias P. Braendli <matthias@mpb.li> -*/ - -#include "charset.h" -#include <iostream> -#include <fstream> - -#include <cstdio> - -using namespace std; - -int main(int argc, char** argv) -{ -    string test_file_path("input.txt"); - -    ifstream fs8(test_file_path); -    if (!fs8.is_open()) { -        cerr << "Could not open " << test_file_path << endl; -        return 1; -    } - -    CharsetConverter conv; - -    string line; -    // Play with all the lines in the file -    while (getline(fs8, line)) { -        cout << conv.convert(line) << endl; -    } - -    return 0; -} - - diff --git a/src/charset.h b/src/charset.h deleted file mode 100644 index 8d1e1a2..0000000 --- a/src/charset.h +++ /dev/null @@ -1,115 +0,0 @@ -/* -    Copyright (C) 2015 Matthias P. Braendli (http://opendigitalradio.org) - -    This program is free software: you can redistribute it and/or modify -    it under the terms of the GNU General Public License as published by -    the Free Software Foundation, either version 3 of the License, or -    (at your option) any later version. - -    This program is distributed in the hope that it will be useful, -    but WITHOUT ANY WARRANTY; without even the implied warranty of -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -    GNU General Public License for more details. - -    You should have received a copy of the GNU General Public License -    along with this program.  If not, see <http://www.gnu.org/licenses/>. -*/ -/*! -    \file charset.h -    \brief Define the EBU charset according to ETSI TS 101 756v1.8.1 for DLS encoding - -    \author Matthias P. Braendli <matthias@mpb.li> -    \author Lindsay Cornell -*/ - -#ifndef __CHARSET_H_ -#define __CHARSET_H_ - -#include "utf8.h" -#include <string> -#include <vector> -#include <algorithm> - -/**********************************************/ -/************* BIG FAT WARNING ****************/ -/**********************************************/ -/**** Make sure this file is always saved  ****/ -/**** encoded in UTF-8, otherwise you will ****/ -/****      mess up the table below !       ****/ -/**********************************************/ -/********* END OF BIG FAT WARNING *************/ -/**********************************************/ - - -#define CHARSET_TABLE_OFFSET 1 // NUL at index 0 cannot be represented -#define CHARSET_TABLE_ENTRIES (256 - CHARSET_TABLE_OFFSET) -const char* utf8_encoded_EBU_Latin[CHARSET_TABLE_ENTRIES] = { -     "Ę", "Į", "Ų", "Ă", "Ė", "Ď", "Ș", "Ț", "Ċ", "\n","\v","Ġ", "Ĺ", "Ż", "Ń", -"ą", "ę", "į", "ų", "ă", "ė", "ď", "ș", "ț", "ċ", "Ň", "Ě", "ġ", "ĺ", "ż", "\u0082", -" ", "!", "\"","#", "ł", "%", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/", -"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", "<", "=", ">", "?", -"@", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", -"P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[", "Ů", "]", "Ł", "_", -"Ą", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", -"p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "«", "ů", "»", "Ľ", "Ħ", -"á", "à", "é", "è", "í", "ì", "ó", "ò", "ú", "ù", "Ñ", "Ç", "Ş", "ß", "¡", "Ÿ", -"â", "ä", "ê", "ë", "î", "ï", "ô", "ö", "û", "ü", "ñ", "ç", "ş", "ğ", "ı", "ÿ", -"Ķ", "Ņ", "©", "Ģ", "Ğ", "ě", "ň", "ő", "Ő", "€", "£", "$", "Ā", "Ē", "Ī", "Ū", -"ķ", "ņ", "Ļ", "ģ", "ļ", "İ", "ń", "ű", "Ű", "¿", "ľ", "°", "ā", "ē", "ī", "ū", -"Á", "À", "É", "È", "Í", "Ì", "Ó", "Ò", "Ú", "Ù", "Ř", "Č", "Š", "Ž", "Ð", "Ŀ", -"Â", "Ä", "Ê", "Ë", "Î", "Ï", "Ô", "Ö", "Û", "Ü", "ř", "č", "š", "ž", "đ", "ŀ", -"Ã", "Å", "Æ", "Œ", "ŷ", "Ý", "Õ", "Ø", "Þ", "Ŋ", "Ŕ", "Ć", "Ś", "Ź", "Ť", "ð", -"ã", "å", "æ", "œ", "ŵ", "ý", "õ", "ø", "þ", "ŋ", "ŕ", "ć", "ś", "ź", "ť", "ħ"}; - -class CharsetConverter -{ -    public: -        CharsetConverter() { -            /*! Build the converstion table that contains the known code points, -             * at the indices corresponding to the EBU Latin table -             */ -            using namespace std; -            for (size_t i = 0; i < CHARSET_TABLE_ENTRIES; i++) { -                string table_entry(utf8_encoded_EBU_Latin[i]); -                string::iterator it = table_entry.begin(); -                uint32_t code_point = utf8::next(it, table_entry.end()); -                m_conversion_table.push_back(code_point); -            } -        } - -        /*! Convert a UTF-8 encoded text line into an EBU Latin encoded byte stream -         */ -        std::string convert(std::string line_utf8) { -            using namespace std; - -            // check for invalid utf-8, we only convert up to the first error -            string::iterator end_it = utf8::find_invalid(line_utf8.begin(), line_utf8.end()); - -            // Convert it to utf-32 -            vector<uint32_t> utf32line; -            utf8::utf8to32(line_utf8.begin(), end_it, back_inserter(utf32line)); - -            string encoded_line(utf32line.size(), '0'); - -            // Try to convert each codepoint -            for (size_t i = 0; i < utf32line.size(); i++) { -                vector<uint32_t>::iterator iter = find(m_conversion_table.begin(), -                        m_conversion_table.end(), utf32line[i]); -                if (iter != m_conversion_table.end()) { -                    size_t index = std::distance(m_conversion_table.begin(), iter); - -                    encoded_line[i] = (char)(index + CHARSET_TABLE_OFFSET); -                } -                else { -                    encoded_line[i] = ' '; -                } -            } -            return encoded_line; -        } - -    private: - -        std::vector<uint32_t> m_conversion_table; -}; - -#endif diff --git a/src/mot-encoder.cpp b/src/mot-encoder.cpp deleted file mode 100644 index 4cb6688..0000000 --- a/src/mot-encoder.cpp +++ /dev/null @@ -1,1831 +0,0 @@ -/* -    Copyright (C) 2014 CSP Innovazione nelle ICT s.c.a r.l. (http://rd.csp.it/) - -    Copyright (C) 2014, 2015 Matthias P. Braendli (http://opendigitalradio.org) - -    Copyright (C) 2015, 2016 Stefan Pöschel (http://opendigitalradio.org) - -    This program is free software: you can redistribute it and/or modify -    it under the terms of the GNU General Public License as published by -    the Free Software Foundation, either version 3 of the License, or -    (at your option) any later version. - -    This program is distributed in the hope that it will be useful, -    but WITHOUT ANY WARRANTY; without even the implied warranty of -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -    GNU General Public License for more details. - -    You should have received a copy of the GNU General Public License -    along with this program.  If not, see <http://www.gnu.org/licenses/>. -*/ -/*! -    \file mot-encoder.cpp -    \brief Generete PAD data for MOT Slideshow and DLS - -    \author Sergio Sagliocco <sergio.sagliocco@csp.it> -    \author Matthias P. Braendli <matthias@mpb.li> -    \author Stefan Pöschel <odr@basicmaster.de> -*/ - -#include <cstdio> -#include <stdlib.h> -#include <stdint.h> -#include <unistd.h> -#include <cstring> -#include <string> -#include <sstream> -#include <iostream> -#include <fstream> -#include <algorithm> -#include <vector> -#include <deque> -#include <list> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <dirent.h> -#include <getopt.h> -#include "config.h" -#include "charset.h" - - -#if HAVE_MAGICKWAND -#  include <wand/magick_wand.h> -#endif - -#define DEBUG 0 - -#define SLEEPDELAY_DEFAULT 10 //seconds - -extern "C" { -#include "lib_crc.h" -} - -#define MIN(a,b) (((a)<(b))?(a):(b)) -#define MAX(a,b) (((a)>(b))?(a):(b)) - -#define XSTR(x) #x -#define STR(x) XSTR(x) - -#define MAXSEGLEN 8189 // Bytes (EN 301 234 v2.1.1, ch. 5.1.1) -#define MAXDLS 128 // chars -#define MAXSLIDESIZE 51200 // Bytes (TS 101 499 v3.1.1, ch. 9.1.2) - -// Roll-over value for fidx -#define MAXSLIDEID 9999 - -// How many slides to keep in history -#define MAXHISTORYLEN 50 - -// Do not allow the image compressor to go below -// JPEG quality 40 -#define MINQUALITY 40 - -// Charsets from TS 101 756 -#define CHARSET_COMPLETE_EBU_LATIN 0 //!< Complete EBU Latin based repertoire -#define CHARSET_EBU_LATIN_CY_GR 1 //!< EBU Latin based common core, Cyrillic, Greek -#define CHARSET_EBU_LATIN_AR_HE_CY_GR 2 //!< EBU Latin based core, Arabic, Hebrew, Cyrillic and Greek -#define CHARSET_ISO_LATIN_ALPHABET_2 3 //!< ISO Latin Alphabet No 2 -#define CHARSET_UCS2_BE 6 //!< ISO/IEC 10646 using UCS-2 transformation format, big endian byte order -#define CHARSET_UTF8 15 //!< ISO Latin Alphabet No 2 - - -typedef std::vector<uint8_t> uint8_vector_t; -static int verbose = 0; - - -struct MSCDG { -    // MSC Data Group Header (extension field not supported) -    unsigned char extflag;      //  1 bit -    unsigned char crcflag;      //  1 bit -    unsigned char segflag;      //  1 bit -    unsigned char accflag;      //  1 bit -    unsigned char dgtype;       //  4 bits -    unsigned char cindex;       //  4 bits -    unsigned char rindex;       //  4 bits -    /// Session header - Segment field -    unsigned char last;         //  1 bit -    unsigned short int segnum;  // 16 bits -    // Session header - User access field -    unsigned char rfa;          //  3 bits -    unsigned char tidflag;      //  1 bit -    unsigned char lenid;        //  4 bits - Fixed to value 2 in this implemntation -    unsigned short int tid;     // 16 bits -    // MSC data group data field -    //  Mot Segmentation header -    unsigned char rcount;       //  3 bits -    unsigned short int seglen;  // 13 bits -    // Mot segment -    unsigned char* segdata; -    // MSC data group CRC -    unsigned short int crc;     // 16 bits -}; - -/*! Between collection of slides and transmission, the slide data is saved - * in this structure. - */ -struct slide_metadata_t { -    // complete path to slide -    std::string filepath; - -    // index, values from 0 to MAXSLIDEID, rolls over -    int fidx; - -    // This is used to define the order in which several discovered -    // slides are transmitted -    bool operator<(const slide_metadata_t& other) const { -        return this->fidx < other.fidx; -    } -}; - -/*! A simple fingerprint for each slide transmitted. - * Allows us to reuse the same fidx if the same slide - * is transmitted more than once. - */ -struct fingerprint_t { -    // file name -    std::string s_name; -    // file size, in bytes -    off_t s_size; -    // time of last modification -    unsigned long s_mtime; - -    // assigned fidx, -1 means invalid -    int fidx; - -    /*! The comparison is not done on fidx, only -     * on the file-specific data -     */ -    bool operator==(const fingerprint_t& other) const { -        return (((s_name == other.s_name && -                 s_size == other.s_size) && -                s_mtime == other.s_mtime)); -    } - -    void disp(void) { -        printf("%s_%ld_%lu:%d\n", s_name.c_str(), s_size, s_mtime, fidx); -    } - -    void load_from_file(const char* filepath) -    { -        struct stat file_attribue; -        const char * final_slash; - -        stat(filepath, &file_attribue); -        final_slash = strrchr(filepath, '/'); - -        // load filename, size and mtime -        // Save only the basename of the filepath -        this->s_name.assign((final_slash == NULL) ? filepath : final_slash + 1); -        this->s_size = file_attribue.st_size; -        this->s_mtime = file_attribue.st_mtime; - -        this->fidx = -1; -    } -}; - -/*! We keep track of transmitted files so that we can retransmit - * identical slides with the same index, in case the receivers cache - * them. - * - * \c MAXHISTORYLEN defines for how how many slides we want to keep this - * history. - */ -class History { -    public: -        History(size_t hist_size) : -            m_hist_size(hist_size), -            m_last_given_fidx(0) {} -        void disp_database(); -        // controller of id base on database -        int get_fidx(const char* filepath); - -    private: -        std::deque<fingerprint_t> m_database; - -        size_t m_hist_size; - -        int m_last_given_fidx; - -        // find the fingerprint fp in database. -        // returns the fidx when found, -        //    or   -1 if not found -        int find(const fingerprint_t& fp) const; - -        // add a new fingerprint into database -        // returns its fidx -        void add(fingerprint_t& fp); -}; - - -int encodeFile(int output_fd, const std::string& fname, int fidx, bool raw_slides); - -uint8_vector_t createMotHeader( -        size_t blobsize, -        int fidx, -        bool jfif_not_png); - -void createMscDG(MSCDG* msc, unsigned short int dgtype, int *cindex, unsigned short int segnum, -        unsigned short int lastseg, unsigned short int tid, unsigned char* data, -        unsigned short int datalen); - -struct DATA_GROUP; -DATA_GROUP* packMscDG(MSCDG* msc); - -struct DL_STATE; -void prepend_dl_dgs(const DL_STATE& dl_state, uint8_t charset); -void writeDLS(int output_fd, const std::string& dls_file, uint8_t charset, bool raw_dls, bool remove_dls); - -// PAD related -#define CRC_LEN 2 - -struct DATA_GROUP { -    uint8_vector_t data; -    int apptype_start; -    int apptype_cont; -    size_t written; - -    DATA_GROUP(size_t len, int apptype_start, int apptype_cont) { -        this->data.resize(len); -        this->apptype_start = apptype_start; -        this->apptype_cont = apptype_cont; -        written = 0; -    } - -    void AppendCRC() { -        uint16_t crc = 0xFFFF; -        for (size_t i = 0; i < data.size(); i++) -            crc = update_crc_ccitt(crc, data[i]); -        crc = ~crc; -#if DEBUG -        fprintf(stderr, "crc=%04x ~crc=%04x\n", crc, ~crc); -#endif - -        data.push_back((crc & 0xFF00) >> 8); -        data.push_back((crc & 0x00FF)); -    } - -    size_t Available() { -        return data.size() - written; -    } - -    int Write(uint8_t *write_data, size_t len, int *cont_apptype) { -        size_t written_now = std::min(len, Available()); - -        // fill up remaining bytes with zero padding -        memcpy(write_data, &data[written], written_now); -        memset(write_data + written_now, 0x00, len - written_now); - -        // set app type depending on progress -        int apptype = written > 0 ? apptype_cont : apptype_start; - -        written += written_now; - -        // prevent continuation of a different DG having the same type -        if (cont_apptype) -            *cont_apptype = Available() > 0 ? apptype_cont : -1; - -        return apptype; -    } -}; - -#define SHORT_PAD 6         // F-PAD + 1x CI              + 1x  3 bytes data sub-field -#define VARSIZE_PAD_MIN 8   // F-PAD + 1x CI + end marker + 1x  4 bytes data sub-field -#define VARSIZE_PAD_MAX 196 // F-PAD + 4x CI              + 4x 48 bytes data sub-field -#define ALLOWED_PADLEN "6 (short X-PAD), 8 to 196 (variable size X-PAD)" - - - -// MOT Slideshow related -static int cindex_header = 0; -static int cindex_body = 0; - - -class MOTHeader { -private: -    size_t header_size; -    uint8_vector_t data; - -    void IncrementHeaderSize(size_t size); -    void AddParamHeader(int pli, int param_id) {data.push_back((pli << 6) | (param_id & 0x3F));} -public: -    MOTHeader(size_t body_size, int content_type, int content_subtype); - -    void AddExtension(int param_id); -    void AddExtension8Bit(int param_id, uint8_t data_field); -    void AddExtension32Bit(int param_id, uint32_t data_field); -    void AddExtensionVarSize(int param_id, const uint8_t* data_field, size_t data_field_len); -    const uint8_vector_t GetData() {return data;} -}; - -MOTHeader::MOTHeader(size_t body_size, int content_type, int content_subtype) -: header_size(0), data(uint8_vector_t(7, 0x00)) { -    // init header core - -    // body size -    data[0] = (body_size >> 20) & 0xFF; -    data[1] = (body_size >> 12) & 0xFF; -    data[2] = (body_size >>  4) & 0xFF; -    data[3] = (body_size <<  4) & 0xF0; - -    // header size -    IncrementHeaderSize(data.size()); - -    // content type -    data[5] |= (content_type << 1) & 0x7E; - -    // content subtype -    data[5] |= (content_subtype >> 8) & 0x01; -    data[6] |=  content_subtype       & 0xFF; -} - -void MOTHeader::IncrementHeaderSize(size_t size) { -    header_size += size; - -    data[3] &= 0xF0; -    data[3] |= (header_size >> 9) & 0x0F; - -    data[4]  = (header_size >> 1) & 0xFF; - -    data[5] &= 0x7F; -    data[5] |= (header_size << 7) & 0x80; -} - -void MOTHeader::AddExtension(int param_id) { -    AddParamHeader(0b00, param_id); - -    IncrementHeaderSize(1); -} - -void MOTHeader::AddExtension8Bit(int param_id, uint8_t data_field) { -    AddParamHeader(0b01, param_id); -    data.push_back(data_field); - -    IncrementHeaderSize(2); -} - -void MOTHeader::AddExtension32Bit(int param_id, uint32_t data_field) { -    AddParamHeader(0b10, param_id); -    data.push_back((data_field >> 24) & 0xFF); -    data.push_back((data_field >> 16) & 0xFF); -    data.push_back((data_field >>  8) & 0xFF); -    data.push_back( data_field        & 0xFF); - -    IncrementHeaderSize(5); -} - -void MOTHeader::AddExtensionVarSize(int param_id, const uint8_t* data_field, size_t data_field_len) { -    AddParamHeader(0b11, param_id); - -    // longer field lens use 15 instead of 7 bits -    bool ext = data_field_len > 127; -    if (ext) { -        data.push_back(0x80 | ((data_field_len >> 8) & 0x7F)); -        data.push_back(data_field_len & 0xFF); -    } else { -        data.push_back(data_field_len & 0x7F); -    } - -    for (size_t i = 0; i < data_field_len; i++) -        data.push_back(data_field[i]); - -    IncrementHeaderSize(1 + (ext ? 2 : 1) + data_field_len); -} - - - -// DLS related -#define FPAD_LEN 2 -#define DLS_SEG_LEN_PREFIX       2 -#define DLS_SEG_LEN_CHAR_MAX    16 -#define DLS_CMD_REMOVE_LABEL    0b0001 -#define DLS_CMD_DL_PLUS         0b0010 -#define DL_PLUS_CMD_TAGS        0b0000 - -#define DL_PARAMS_OPEN          "##### parameters { #####" -#define DL_PARAMS_CLOSE         "##### parameters } #####" - -CharsetConverter charset_converter; - -struct DL_PLUS_TAG { -    int content_type; -    int start_marker; -    int length_marker; - -    DL_PLUS_TAG() : -        content_type(0),    // = DUMMY -        start_marker(0), -        length_marker(0) -    {} - -    DL_PLUS_TAG(int content_type, int start_marker, int length_marker) : -        content_type(content_type), -        start_marker(start_marker), -        length_marker(length_marker) -    {} - -    bool operator==(const DL_PLUS_TAG& other) const { -        return -            content_type == other.content_type && -            start_marker == other.start_marker && -            length_marker == other.length_marker; -    } -    bool operator!=(const DL_PLUS_TAG& other) const { -        return !(*this == other); -    } -}; - -typedef std::vector<DL_PLUS_TAG> dl_plus_tags_t; - -struct DL_STATE { -    std::string dl_text; - -    bool dl_plus_enabled; -    bool dl_plus_item_toggle; -    bool dl_plus_item_running; -    dl_plus_tags_t dl_plus_tags; - -    DL_STATE() : -        dl_plus_enabled(false), -        dl_plus_item_toggle(false), -        dl_plus_item_running(false) -    {} - -    bool operator==(const DL_STATE& other) const { -        if (dl_text != other.dl_text) -            return false; -        if (dl_plus_enabled != other.dl_plus_enabled) -            return false; -        if (dl_plus_enabled) { -            if (dl_plus_item_toggle != other.dl_plus_item_toggle) -                return false; -            if (dl_plus_item_running != other.dl_plus_item_running) -                return false; -            if (dl_plus_tags != other.dl_plus_tags) -                return false; -        } -        return true; -    } -    bool operator!=(const DL_STATE& other) const { -        return !(*this == other); -    } -}; - - -typedef uint8_vector_t pad_t; -static bool dls_toggle = false; -static DL_STATE dl_state_prev; - - -class PADPacketizer { -private: -    static const size_t subfield_lens[]; - -    const size_t xpad_size_max; -    const bool short_xpad; -    const size_t max_cis; - -    size_t xpad_size; -    uint8_t subfields[4*48]; -    size_t subfields_size; - -    // PAD w/  CI list -    int ci_type[4]; -    size_t ci_len_index[4]; -    size_t used_cis; - -    // PAD w/o CI list -    int last_ci_type; -    size_t last_ci_size; - -    size_t AddCINeededBytes(); -    void AddCI(int apptype, int len_index); - -    int OptimalSubFieldSizeIndex(size_t available_bytes); -    int WriteDGToSubField(DATA_GROUP* dg, size_t len); - -    bool AppendDG(DATA_GROUP* dg); -    void AppendDGWithCI(DATA_GROUP* dg); -    void AppendDGWithoutCI(DATA_GROUP* dg); - -    void ResetPAD(); -    pad_t* FlushPAD(); -public: -    std::deque<DATA_GROUP*> queue; - -    PADPacketizer(size_t pad_size); -    ~PADPacketizer(); - -    pad_t* GetPAD(); - -    // will be removed, when pull (instead of push) approach is implemented! -    void WriteAllPADs(int output_fd); -}; - - -const size_t PADPacketizer::subfield_lens[] = {4, 6, 8, 12, 16, 24, 32, 48}; - -PADPacketizer::PADPacketizer(size_t pad_size) : -    xpad_size_max(pad_size - FPAD_LEN), -    short_xpad(pad_size == SHORT_PAD), -    max_cis(short_xpad ? 1 : 4), -    last_ci_type(-1) -{ -    ResetPAD(); -} - -PADPacketizer::~PADPacketizer() { -    while (!queue.empty()) { -        delete queue.front(); -        queue.pop_front(); -    } -} - - -pad_t* PADPacketizer::GetPAD() { -    bool pad_flushable = false; - -    // process DG queue -    while (!pad_flushable && !queue.empty()) { -        DATA_GROUP* dg = queue.front(); - -        // repeatedly append DG -        while (!pad_flushable && dg->Available() > 0) -            pad_flushable = AppendDG(dg); - -        if (dg->Available() == 0) { -            delete dg; -            queue.pop_front(); -        } -    } - -    // (possibly empty) PAD -    return FlushPAD(); -} - -void PADPacketizer::WriteAllPADs(int output_fd) { -    for (;;) { -        pad_t* pad = GetPAD(); - -        // if only F-PAD present, abort -        if (pad->back() == FPAD_LEN) { -            delete pad; -            break; -        } - -        if (write(output_fd, &(*pad)[0], pad->size()) != (signed) pad->size()) -            fprintf(stderr, "mot-encoder Error: Could not write PAD\n"); - -        delete pad; -    } -} - - -size_t PADPacketizer::AddCINeededBytes() { -    // returns the amount of additional bytes needed for the next CI - -    // special cases: end marker added/replaced -    if (!short_xpad && used_cis == 0) -        return 2; -    if (!short_xpad && used_cis == (max_cis - 1)) -        return 0; -    return 1; -} - -void PADPacketizer::AddCI(int apptype, int len_index) { -    ci_type[used_cis] = apptype; -    ci_len_index[used_cis] = len_index; - -    xpad_size += AddCINeededBytes(); -    used_cis++; -} - - -int PADPacketizer::OptimalSubFieldSizeIndex(size_t available_bytes) { -    /*! Return the index of the optimal sub-field size by stepwise search (regards only Variable Size X-PAD): -     * - find the smallest sub-field able to hold (at least) all available bytes -     * - find the biggest regarding sub-field we have space for (which definitely exists - otherwise previously the PAD would have been flushed) -     * - if the wasted space is at least as big as the smallest possible sub-field, use a sub-field one size smaller -     */ -    int len_index = 0; - -    while ((len_index + 1) < 8 && subfield_lens[len_index] < available_bytes) -        len_index++; -    while ((len_index - 1) >= 0 && (subfield_lens[len_index] + AddCINeededBytes()) > (xpad_size_max - xpad_size)) -        len_index--; -    if ((len_index - 1) >= 0 && ((int) subfield_lens[len_index] - (int) available_bytes) >= (int) subfield_lens[0]) -        len_index--; - -    return len_index; -} - -int PADPacketizer::WriteDGToSubField(DATA_GROUP* dg, size_t len) { -    int apptype = dg->Write(&subfields[subfields_size], len, &last_ci_type); -    subfields_size += len; -    xpad_size += len; -    return apptype; -} - - -bool PADPacketizer::AppendDG(DATA_GROUP* dg) { -    /*! use X-PAD w/o CIs instead of X-PAD w/ CIs, if we can save some bytes or at least do not waste additional bytes -     * -     * Omit CI list in case: -     * 1.   no pending data sub-fields -     * 2.   last CI type valid -     * 3.   last CI type matching current (continuity) CI type -     * 4a.  short X-PAD; OR -     * 4ba. size of the last X-PAD being at least as big as the available X-PAD payload in case all CIs are used AND -     * 4bb. the amount of available DG bytes being at least as big as the size of the last X-PAD in case all CIs are used -     */ -    if ( -            used_cis == 0 && -            last_ci_type != -1 && -            last_ci_type == dg->apptype_cont && -            (short_xpad || -                    (last_ci_size >= (xpad_size_max - max_cis) && -                            dg->Available() >= (last_ci_size - max_cis))) -            ) { -        AppendDGWithoutCI(dg); -        return true; -    } else { -        AppendDGWithCI(dg); - -        // if no further sub-fields could be added, PAD must be flushed -        if (used_cis == max_cis || subfield_lens[0] + AddCINeededBytes() > (xpad_size_max - xpad_size)) -            return true; -    } -    return false; -} - - -void PADPacketizer::AppendDGWithCI(DATA_GROUP* dg) { -    int len_index = short_xpad ? 0 : OptimalSubFieldSizeIndex(dg->Available()); -    size_t len_size = short_xpad ? 3 : subfield_lens[len_index]; - -    int apptype = WriteDGToSubField(dg, len_size); -    AddCI(apptype, len_index); - -#if DEBUG -    fprintf(stderr, "PADPacketizer: added sub-field w/  CI - type: %2d, size: %2zu\n", apptype, len_size); -#endif -} - -void PADPacketizer::AppendDGWithoutCI(DATA_GROUP* dg) { -#if DEBUG -    int old_last_ci_type = last_ci_type; -#endif - -    WriteDGToSubField(dg, last_ci_size); - -#if DEBUG -    fprintf(stderr, "PADPacketizer: added sub-field w/o CI - type: %2d, size: %2zu\n", old_last_ci_type, last_ci_size); -#endif -} - -void PADPacketizer::ResetPAD() { -    xpad_size = 0; -    subfields_size = 0; -    used_cis = 0; -} - -pad_t* PADPacketizer::FlushPAD() { -    pad_t* result = new pad_t(xpad_size_max + FPAD_LEN + 1); -    pad_t &pad = *result; - -    size_t pad_offset = xpad_size_max; - -    if (subfields_size > 0) { -        if (used_cis > 0) { -            // X-PAD: CIs -            for (size_t i = 0; i < used_cis; i++) -                pad[--pad_offset] = (short_xpad ? 0 : ci_len_index[i]) << 5 | ci_type[i]; - -            // X-PAD: end marker (if needed) -            if (used_cis < max_cis) -                pad[--pad_offset] = 0x00; -        } - -        // X-PAD: sub-fields (reversed on-the-fly) -        for (size_t off = 0; off < subfields_size; off++) -            pad[--pad_offset] = subfields[off]; -    } else { -        // no X-PAD -        last_ci_type = -1; -    } - -    // zero padding -    memset(&pad[0], 0x00, pad_offset); - -    // F-PAD -    pad[xpad_size_max + 0] = subfields_size > 0 ? (short_xpad ? 0x10 : 0x20) : 0x00; -    pad[xpad_size_max + 1] = subfields_size > 0 ? (used_cis > 0 ? 0x02 : 0x00) : 0x00; - -    // used PAD len -    pad[xpad_size_max + FPAD_LEN] = xpad_size + FPAD_LEN; - -    last_ci_size = xpad_size; -    ResetPAD(); -    return result; -} - - -static PADPacketizer *pad_packetizer; - - - - - - - -void usage(char* name) -{ -    fprintf(stderr, "DAB MOT encoder %s for slideshow and DLS\n\n" -                    "By CSP Innovazione nelle ICT s.c.a r.l. (http://rd.csp.it/) and\n" -                    "Opendigitalradio.org\n\n" -                    "Reads image data from the specified directory, DLS text from a file,\n" -                    "and outputs PAD data to the given FIFO.\n" -                    "  http://opendigitalradio.org\n\n", -#if defined(GITVERSION) -                    GITVERSION -#else -                    PACKAGE_VERSION -#endif -                    ); -    fprintf(stderr, "Usage: %s [OPTIONS...]\n", name); -    fprintf(stderr, " -d, --dir=DIRNAME      Directory to read images from.\n" -                    " -e, --erase            Erase slides from DIRNAME once they have\n" -                    "                          been encoded.\n" -                    " -s, --sleep=DELAY      Wait DELAY seconds between each slide\n" -                    "                          Default: " STR(SLEEPDELAY_DEFAULT) "\n" -                    " -o, --output=FILENAME  Fifo to write PAD data into.\n" -                    "                          Default: /tmp/pad.fifo\n" -                    " -t, --dls=FILENAME     Fifo or file to read DLS text from.\n" -                    " -p, --pad=LENGTH       Set the pad length.\n" -                    "                          Possible values: " ALLOWED_PADLEN "\n" -                    "                          Default: 58\n" -                    " -c, --charset=ID       ID of the character set encoding used for DLS text input.\n" -                    "                          ID =  0: Complete EBU Latin based repertoire\n" -                    "                          ID =  6: ISO/IEC 10646 using UCS-2 BE\n" -                    "                          ID = 15: ISO/IEC 10646 using UTF-8\n" -                    "                          Default: 15\n" -                    " -r, --remove-dls       Always insert a DLS Remove Label command when replacing a DLS text.\n" -                    " -C, --raw-dls          Do not convert DLS texts to Complete EBU Latin based repertoire\n" -                    "                          character set encoding.\n" -                    " -R, --raw-slides       Do not process slides. Integrity checks and resizing\n" -                    "                          slides is skipped. Use this if you know what you are doing !\n" -                    "                          It is useful only when -d is used\n" -                    " -v, --verbose          Print more information to the console\n" -           ); -} - -#define no_argument 0 -#define required_argument 1 -#define optional_argument 2 -int main(int argc, char *argv[]) -{ -    int ret; -    struct dirent *pDirent; -    int  padlen = 58; -    bool erase_after_tx = false; -    int  sleepdelay = SLEEPDELAY_DEFAULT; -    bool raw_slides = false; -    int  charset = CHARSET_UTF8; -    bool raw_dls = false; -    bool remove_dls = false; - -    const char* sls_dir = NULL; -    const char* output = "/tmp/pad.fifo"; -    std::string dls_file; - -    const struct option longopts[] = { -        {"charset",    required_argument,  0, 'c'}, -        {"raw-dls",    no_argument,        0, 'C'}, -        {"remove-dls", no_argument,        0, 'r'}, -        {"dir",        required_argument,  0, 'd'}, -        {"erase",      no_argument,        0, 'e'}, -        {"output",     required_argument,  0, 'o'}, -        {"dls",        required_argument,  0, 't'}, -        {"pad",        required_argument,  0, 'p'}, -        {"sleep",      required_argument,  0, 's'}, -        {"raw-slides", no_argument,        0, 'R'}, -        {"help",       no_argument,        0, 'h'}, -        {"verbose",    no_argument,        0, 'v'}, -        {0,0,0,0}, -    }; - -    int ch=0; -    int index; -    while(ch != -1) { -        ch = getopt_long(argc, argv, "eChRrc:d:o:p:s:t:v", longopts, &index); -        switch (ch) { -            case 'c': -                charset = atoi(optarg); -                break; -            case 'C': -                raw_dls = true; -                break; -            case 'r': -                remove_dls = true; -                break; -            case 'd': -                sls_dir = optarg; -                break; -            case 'e': -                erase_after_tx = true; -                break; -            case 'o': -                output = optarg; -                break; -            case 's': -                sleepdelay = atoi(optarg); -                break; -            case 't': -                dls_file = optarg; -                break; -            case 'p': -                padlen = atoi(optarg); -                break; -            case 'R': -                raw_slides = true; -                break; -            case 'v': -                verbose++; -                break; -            case '?': -            case 'h': -                usage(argv[0]); -                return 0; -        } -    } - -    if (padlen != SHORT_PAD && (padlen < VARSIZE_PAD_MIN || padlen > VARSIZE_PAD_MAX)) { -        fprintf(stderr, "mot-encoder Error: pad length %d invalid: Possible values: " -                ALLOWED_PADLEN "\n", -                padlen); -        return 2; -    } - -    if (sls_dir && not dls_file.empty()) { -        fprintf(stderr, "mot-encoder encoding Slideshow from '%s' and DLS from '%s' to '%s'\n", -                sls_dir, dls_file.c_str(), output); -    } -    else if (sls_dir) { -        fprintf(stderr, "mot-encoder encoding Slideshow from '%s' to '%s'. No DLS.\n", -                sls_dir, output); -    } -    else if (not dls_file.empty()) { -        fprintf(stderr, "mot-encoder encoding DLS from '%s' to '%s'. No Slideshow.\n", -                dls_file.c_str(), output); -    } -    else { -        fprintf(stderr, "mot-encoder Error: No DLS nor slideshow to encode !\n"); -        usage(argv[0]); -        return 1; -    } - -    const char* user_charset; -    switch (charset) { -        case CHARSET_COMPLETE_EBU_LATIN: -            user_charset = "Complete EBU Latin"; -            break; -        case CHARSET_EBU_LATIN_CY_GR: -            user_charset = "EBU Latin core, Cyrillic, Greek"; -            break; -        case CHARSET_EBU_LATIN_AR_HE_CY_GR: -            user_charset = "EBU Latin core, Arabic, Hebrew, Cyrillic, Greek"; -            break; -        case CHARSET_ISO_LATIN_ALPHABET_2: -            user_charset = "ISO Latin Alphabet 2"; -            break; -        case CHARSET_UCS2_BE: -            user_charset = "UCS-2 BE"; -            break; -        case CHARSET_UTF8: -            user_charset = "UTF-8"; -            break; -        default: -            user_charset = "Invalid"; -            charset = -1; -            break; -    } - -    if (charset == -1) { -        fprintf(stderr, "mot-encoder Error: Invalid charset!\n"); -        usage(argv[0]); -        return 1; -    } -    else { -        fprintf(stderr, "mot-encoder using charset %s (%d)\n", -               user_charset, charset); -    } - -    if (not raw_dls) { -        switch (charset) { -        case CHARSET_COMPLETE_EBU_LATIN: -            // no conversion needed -            break; -        case CHARSET_UTF8: -            fprintf(stderr, "mot-encoder converting DLS texts to Complete EBU Latin\n"); -            break; -        default: -            fprintf(stderr, "mot-encoder Error: DLS conversion to EBU is currently only supported for UTF-8 input!\n"); -            return 1; -        } -    } - -    int output_fd = open(output, O_WRONLY); -    if (output_fd == -1) { -        perror("mot-encoder Error: failed to open output"); -        return 3; -    } - -#if HAVE_MAGICKWAND -    MagickWandGenesis(); -#endif - -    pad_packetizer = new PADPacketizer(padlen); - -    std::list<slide_metadata_t> slides_to_transmit; -    History slides_history(MAXHISTORYLEN); - -    while(1) { -        if (sls_dir) { // slide + possibly DLS -            DIR *pDir = opendir(sls_dir); -            if (pDir == NULL) { -                fprintf(stderr, "mot-encoder Error: cannot open directory '%s'\n", sls_dir); -                return 1; -            } - -            // Add new slides to transmit to list -            while ((pDirent = readdir(pDir)) != NULL) { -                if (pDirent->d_name[0] != '.') { -                    char imagepath[256]; -                    sprintf(imagepath, "%s/%s", sls_dir, pDirent->d_name); - -                    slide_metadata_t md; -                    md.filepath = imagepath; -                    md.fidx     = slides_history.get_fidx(imagepath); -                    slides_to_transmit.push_back(md); - -                    if (verbose) { -                        fprintf(stderr, "mot-encoder found slide '%s', fidx %d\n", imagepath, md.fidx); -                    } -                } -            } - -            closedir(pDir); - -#if DEBUG -            slides_history.disp_database(); -#endif - -            // if ATM no slides, transmit at least DLS -            if (slides_to_transmit.empty()) { -                if (not dls_file.empty()) -                    writeDLS(output_fd, dls_file, charset, raw_dls, remove_dls); - -                sleep(sleepdelay); -            } else { -                // Sort the list in fidx order -                slides_to_transmit.sort(); - -                // Encode the slides -                for (std::list<slide_metadata_t>::const_iterator it = slides_to_transmit.cbegin(); -                        it != slides_to_transmit.cend(); -                        ++it) { - -                    ret = encodeFile(output_fd, it->filepath, it->fidx, raw_slides); -                    if (ret != 1) -                        fprintf(stderr, "mot-encoder Error: cannot encode file '%s'\n", it->filepath.c_str()); - -                    if (erase_after_tx) { -                        if (unlink(it->filepath.c_str()) == -1) { -                            fprintf(stderr, "mot-encoder Error: erasing file '%s' failed: ", it->filepath.c_str()); -                            perror(""); -                        } -                    } - -                    // Always retransmit DLS after each slide, we want it to be updated frequently -                    if (not dls_file.empty()) -                        writeDLS(output_fd, dls_file, charset, raw_dls, remove_dls); - -                    sleep(sleepdelay); -                } - -                slides_to_transmit.resize(0); -            } -        } else { // only DLS -            // Always retransmit DLS, we want it to be updated frequently -            writeDLS(output_fd, dls_file, charset, raw_dls, remove_dls); - -            sleep(sleepdelay); -        } -    } - -    delete pad_packetizer; - -    return 1; -} - - -DATA_GROUP* createDataGroupLengthIndicator(size_t len) { -    DATA_GROUP* dg = new DATA_GROUP(2, 1, 1);    // continuation never used (except for comparison at short X-PAD) -    uint8_vector_t &data = dg->data; - -    // Data Group length -    data[0] = (len & 0x3F00) >> 8; -    data[1] = (len & 0x00FF); - -    // CRC -    dg->AppendCRC(); - -    return dg; -} - - -void warnOnSmallerImage(size_t height, size_t width, const std::string& fname) { -    if (height < 240 || width < 320) -        fprintf(stderr, "mot-encoder Warning: Image '%s' smaller than recommended size (%zu x %zu < 320 x 240 px)\n", fname.c_str(), width, height); -} - - -/*! Scales the image down if needed, - * so that it is 320x240 pixels. - * Automatically reduces the quality to make sure the - * blobsize is not too large. - * - * \return the blobsize - */ -#if HAVE_MAGICKWAND -size_t resizeImage(MagickWand* m_wand, unsigned char** blob, const std::string& fname, bool* jfif_not_png) -{ -    unsigned char* blob_png; -    unsigned char* blob_jpg; -    size_t blobsize_png; -    size_t blobsize_jpg; - -    size_t height = MagickGetImageHeight(m_wand); -    size_t width  = MagickGetImageWidth(m_wand); - -    while (height > 240 || width > 320) { -        if (height/240.0 > width/320.0) { -            width = width * 240.0 / height; -            height = 240; -        } -        else { -            height = height * 320.0 / width; -            width = 320; -        } -        MagickResizeImage(m_wand, width, height, LanczosFilter, 1); -    } - -    height = MagickGetImageHeight(m_wand); -    width  = MagickGetImageWidth(m_wand); - -    // try PNG (zlib level 9 / possibly adaptive filtering) -    MagickSetImageFormat(m_wand, "png"); -    MagickSetImageCompressionQuality(m_wand, 95); -    blob_png = MagickGetImageBlob(m_wand, &blobsize_png); - -    // try JPG -    MagickSetImageFormat(m_wand, "jpg"); - -    blob_jpg = NULL; -    int quality_jpg = 100; -    do { -        free(blob_jpg); -        quality_jpg -= 5; - -        MagickSetImageCompressionQuality(m_wand, quality_jpg); -        blob_jpg = MagickGetImageBlob(m_wand, &blobsize_jpg); -    } while (blobsize_jpg > MAXSLIDESIZE && quality_jpg > MINQUALITY); - - -    // check for max size -    if (blobsize_png > MAXSLIDESIZE && blobsize_jpg > MAXSLIDESIZE) { -        fprintf(stderr, "mot-encoder: Image Size too large after compression: %zu bytes (PNG), %zu bytes (JPEG)\n", -                blobsize_png, blobsize_jpg); -        free(blob_png); -        free(blob_jpg); -        return 0; -    } - -    // choose the smaller one (at least one does not exceed the max size) -    *jfif_not_png = blobsize_jpg < blobsize_png; - -    if (verbose) { -        if (*jfif_not_png) -            fprintf(stderr, "mot-encoder resized image to %zu x %zu. Size after compression %zu bytes (JPEG, q=%d; PNG was %zu bytes)\n", -                    width, height, blobsize_jpg, quality_jpg, blobsize_png); -        else -            fprintf(stderr, "mot-encoder resized image to %zu x %zu. Size after compression %zu bytes (PNG; JPEG was %zu bytes)\n", -                    width, height, blobsize_png, blobsize_jpg); -    } - -    // warn if resized image smaller than default dimension -    warnOnSmallerImage(height, width, fname); - -    free(*jfif_not_png ? blob_png : blob_jpg); -    *blob = *jfif_not_png ? blob_jpg : blob_png; -    return *jfif_not_png ? blobsize_jpg : blobsize_png; -} -#endif - -int encodeFile(int output_fd, const std::string& fname, int fidx, bool raw_slides) -{ -    int ret = 0; -    int nseg, lastseglen, i, last, curseglen; -#if HAVE_MAGICKWAND -    MagickWand *m_wand = NULL; -    MagickBooleanType err; -#endif -    size_t blobsize, height, width; -    bool jpeg_progr; -    unsigned char *blob = NULL; -    unsigned char *curseg = NULL; -    MSCDG msc; -    DATA_GROUP* dgli; -    DATA_GROUP* mscdg; - -    size_t orig_quality; -    char*  orig_format = NULL; -    /*! We handle JPEG differently, because we want to avoid recompressing the -     * image if it is suitable as is -     */ -    bool orig_is_jpeg = false; - -    /*! If the original is a PNG, we transmit it as is, if the resolution is correct -     * and the file is not too large. Otherwise it gets resized and sent as JPEG. -     */ -    bool orig_is_png = false; - -    /*! By default, we do resize the image to 320x240, with a quality such that -     * the blobsize is at most MAXSLIDESIZE. -     * -     * For JPEG input files that are already at the right resolution and at the -     * right blobsize, we disable this to avoid quality loss due to recompression -     * -     * As device support of this feature is optional, we furthermore require JPEG input -     * files to not have progressive coding. -     */ -    bool resize_required = true; - -    bool jfif_not_png = true; - -    if (!raw_slides) { -#if HAVE_MAGICKWAND - -        m_wand = NewMagickWand(); - -        err = MagickReadImage(m_wand, fname.c_str()); -        if (err == MagickFalse) { -            fprintf(stderr, "mot-encoder Error: Unable to load image '%s'\n", -                    fname.c_str()); - -            goto encodefile_out; -        } - -        height       = MagickGetImageHeight(m_wand); -        width        = MagickGetImageWidth(m_wand); -        orig_format  = MagickGetImageFormat(m_wand); -        jpeg_progr   = MagickGetImageInterlaceScheme(m_wand) == JPEGInterlace; - -        // By default assume that the image has full quality and can be reduced -        orig_quality = 100; - -        // strip unneeded information (profiles, meta data) -        MagickStripImage(m_wand); - -        if (orig_format) { -            if (strcmp(orig_format, "JPEG") == 0) { -                orig_quality = MagickGetImageCompressionQuality(m_wand); -                orig_is_jpeg = true; - -                if (verbose) { -                    fprintf(stderr, "mot-encoder image: '%s' (id=%d)." -                            " Original size: %zu x %zu. (%s, q=%zu, progr=%s)\n", -                            fname.c_str(), fidx, width, height, orig_format, orig_quality, jpeg_progr ? "y" : "n"); -                } -            } -            else if (strcmp(orig_format, "PNG") == 0) { -                orig_is_png = true; -                jfif_not_png = false; - -                if (verbose) { -                    fprintf(stderr, "mot-encoder image: '%s' (id=%d)." -                            " Original size: %zu x %zu. (%s)\n", -                            fname.c_str(), fidx, width, height, orig_format); -                } -            } -            else if (verbose) { -                fprintf(stderr, "mot-encoder image: '%s' (id=%d)." -                        " Original size: %zu x %zu. (%s)\n", -                        fname.c_str(), fidx, width, height, orig_format); -            } - -            free(orig_format); -        } -        else { -            fprintf(stderr, "mot-encoder Warning: Unable to detect image format of '%s'\n", -                    fname.c_str()); - -            fprintf(stderr, "mot-encoder image: '%s' (id=%d).  Original size: %zu x %zu.\n", -                    fname.c_str(), fidx, width, height); -        } - -        if ((orig_is_jpeg || orig_is_png) && height <= 240 && width <= 320 && not jpeg_progr) { -            // Don't recompress the image and check if the blobsize is suitable -            blob = MagickGetImageBlob(m_wand, &blobsize); - -            if (blobsize <= MAXSLIDESIZE) { -                if (verbose) { -                    fprintf(stderr, "mot-encoder image: '%s' (id=%d).  No resize needed: %zu Bytes\n", -                            fname.c_str(), fidx, blobsize); -                } -                resize_required = false; -            } -        } - -        if (resize_required) { -            blobsize = resizeImage(m_wand, &blob, fname, &jfif_not_png); -        } -        else { -            // warn if unresized image smaller than default dimension -            warnOnSmallerImage(height, width, fname); -        } - -#else -        fprintf(stderr, "mot-encoder has not been compiled with MagickWand, only RAW slides are supported!\n"); -        ret = -1; -        goto encodefile_out; -#endif -    } -    else { // Use RAW data, it might not even be a jpg ! -        // read file -        FILE* pFile = fopen(fname.c_str(), "rb"); -        if (pFile == NULL) { -            fprintf(stderr, "mot-encoder Error: Unable to load file '%s'\n", -                    fname.c_str()); -            goto encodefile_out; -        } - -        // obtain file size: -        fseek(pFile, 0, SEEK_END); -        blobsize = ftell(pFile); -        rewind(pFile); - -        if (blobsize > MAXSLIDESIZE) { -            fprintf(stderr, "mot-encoder Warning: blob in raw-slide '%s' too large\n", -                    fname.c_str()); -        } - -        // allocate memory to contain the whole file: -        blob = (unsigned char*)malloc(sizeof(char) * blobsize); -        if (blob == NULL) { -            fprintf(stderr, "mot-encoder Error: Memory allocation error\n"); -            goto encodefile_out; -        } - -        // copy the file into the buffer: -        if (fread(blob, blobsize, 1, pFile) != 1) { -            fprintf(stderr, "mot-encoder Error: Could not read file\n"); -            goto encodefile_out; -        } - -        size_t last_dot = fname.rfind("."); - -        // default: -        jfif_not_png = true; // This is how we did it in the past. -                             // It's wrong anyway, so we're at least compatible - -        if (last_dot != std::string::npos) { -            std::string file_extension = fname.substr(last_dot, std::string::npos); - -            std::transform(file_extension.begin(), file_extension.end(), file_extension.begin(), ::tolower); - -            if (file_extension == ".png") { -                jfif_not_png = false; -            } -        } - -        if (pFile != NULL) { -            fclose(pFile); -        } -    } - -    if (blobsize) { -        nseg = blobsize / MAXSEGLEN; -        lastseglen = blobsize % MAXSEGLEN; -        if (lastseglen != 0) { -            nseg++; -        } - -        uint8_vector_t mothdr = createMotHeader(blobsize, fidx, jfif_not_png); -        // Create the MSC Data Group C-Structure -        createMscDG(&msc, 3, &cindex_header, 0, 1, fidx, &mothdr[0], mothdr.size()); -        // Generate the MSC DG frame (Figure 9 en 300 401) -        mscdg = packMscDG(&msc); -        dgli = createDataGroupLengthIndicator(mscdg->data.size()); - -        pad_packetizer->queue.push_back(dgli); -        pad_packetizer->queue.push_back(mscdg); - -        for (i = 0; i < nseg; i++) { -            curseg = blob + i * MAXSEGLEN; -            if (i == nseg-1) { -                curseglen = lastseglen; -                last = 1; -            } -            else { -                curseglen = MAXSEGLEN; -                last = 0; -            } - -            createMscDG(&msc, 4, &cindex_body, i, last, fidx, curseg, curseglen); -            mscdg = packMscDG(&msc); -            dgli = createDataGroupLengthIndicator(mscdg->data.size()); - -            pad_packetizer->queue.push_back(dgli); -            pad_packetizer->queue.push_back(mscdg); -        } - -        pad_packetizer->WriteAllPADs(output_fd); - -        ret = 1; -    } - -encodefile_out: -#if HAVE_MAGICKWAND -    if (m_wand) { -        m_wand = DestroyMagickWand(m_wand); -    } -#endif - -    if (blob) { -        free(blob); -    } -    return ret; -} - - -uint8_vector_t createMotHeader(size_t blobsize, int fidx, bool jfif_not_png) -{ -    // prepare ContentName -    uint8_t cntemp[10];     // = 1 + 8 + 1 = charset + name + terminator -    cntemp[0] = 0x0 << 4;   // charset: 0 (Complete EBU Latin based) - doesn't really matter here -    snprintf((char*) (cntemp + 1), sizeof(cntemp) - 1, "%04d.%s", fidx, jfif_not_png ? "jpg" : "png"); -    if (verbose) -        fprintf(stderr, "mot-encoder writing image as '%s'\n", cntemp + 1); - -    // MOT header - content type: image, content subtype: JFIF / PNG -    MOTHeader header(blobsize, 0x02, jfif_not_png ? 0x001 : 0x003); - -    // TriggerTime: NOW -    header.AddExtension32Bit(0x05, 0x00000000); - -    // ContentName: XXXX.jpg / XXXX.png -    header.AddExtensionVarSize(0x0C, cntemp, sizeof(cntemp) - 1);   // omit terminator - -    return header.GetData(); -} - - -void createMscDG(MSCDG* msc, unsigned short int dgtype, -        int *cindex, unsigned short int segnum, unsigned short int lastseg, -        unsigned short int tid, unsigned char* data, -        unsigned short int datalen) -{ -    msc->extflag = 0; -    msc->crcflag = 1; -    msc->segflag = 1; -    msc->accflag = 1; -    msc->dgtype = dgtype; -    msc->cindex = *cindex; -    msc->rindex = 0; -    msc->last = lastseg; -    msc->segnum = segnum; -    msc->rfa = 0; -    msc->tidflag = 1; -    msc->lenid = 2; -    msc->tid = tid; -    msc->segdata = data; -    msc->rcount = 0; -    msc->seglen = datalen; - -    *cindex = (*cindex + 1) % 16;   // increment continuity index -} - - -DATA_GROUP* packMscDG(MSCDG* msc) -{ -    DATA_GROUP* dg = new DATA_GROUP(9 + msc->seglen, 12, 13); -    uint8_vector_t &b = dg->data; - -    // headers -    b[0] = (msc->extflag<<7) | (msc->crcflag<<6) | (msc->segflag<<5) | -           (msc->accflag<<4) | msc->dgtype; - -    b[1] = (msc->cindex<<4) | msc->rindex; -    b[2] = (msc->last<<7) | ((msc->segnum & 0x7F00) >> 8); -    b[3] =  msc->segnum & 0x00FF; -    b[4] = 0; -    b[4] = (msc->rfa << 5) | (msc->tidflag << 4) | msc->lenid; -    b[5] = (msc->tid & 0xFF00) >> 8; -    b[6] =  msc->tid & 0x00FF; -    b[7] = (msc->rcount << 5) | ((msc->seglen & 0x1F00)>>8); -    b[8] =  msc->seglen & 0x00FF; - -    // data field -    memcpy(&b[9], msc->segdata, msc->seglen); - -    // CRC -    dg->AppendCRC(); - -    return dg; -} - - -DATA_GROUP* createDynamicLabelCommand(uint8_t command) { -    DATA_GROUP* dg = new DATA_GROUP(2, 2, 3); -    uint8_vector_t &seg_data = dg->data; - -    // prefix: toggle? + first seg + last seg + command flag + command -    seg_data[0] = -            (dls_toggle ? (1 << 7) : 0) + -            (1 << 6) + -            (1 << 5) + -            (1 << 4) + -            command; - -    // prefix: charset (though irrelevant here) -    seg_data[1] = CHARSET_COMPLETE_EBU_LATIN; - -    // CRC -    dg->AppendCRC(); - -    return dg; -} - -DATA_GROUP* createDynamicLabelPlus(const DL_STATE& dl_state) { -    size_t tags_size = dl_state.dl_plus_tags.size(); -    size_t len_dl_plus_cmd_field = 1 + 3 * tags_size; -    DATA_GROUP* dg = new DATA_GROUP(2 + len_dl_plus_cmd_field, 2, 3); -    uint8_vector_t &seg_data = dg->data; - -    // prefix: toggle? + first seg + last seg + command flag + command -    seg_data[0] = -            (dls_toggle ? (1 << 7) : 0) + -            (1 << 6) + -            (1 << 5) + -            (1 << 4) + -            DLS_CMD_DL_PLUS; - -    // prefix: link bit + length -    seg_data[1] = -            (dls_toggle ? (1 << 7) : 0) + -            (len_dl_plus_cmd_field - 1);    // -1 ! - -    // DL Plus tags command: CId + IT + IR + NT -    seg_data[2] = -            (DL_PLUS_CMD_TAGS << 4) + -            (dl_state.dl_plus_item_toggle ? (1 << 3) : 0) + -            (dl_state.dl_plus_item_running ? (1 << 2) : 0) + -            (tags_size - 1);                // -1 ! - -    for (size_t i = 0; i < tags_size; i++) { -        // DL Plus tags command: Content Type + Start Marker + Length Marker -        seg_data[3 + 3 * i] = dl_state.dl_plus_tags[i].content_type & 0x7F; -        seg_data[4 + 3 * i] = dl_state.dl_plus_tags[i].start_marker & 0x7F; -        seg_data[5 + 3 * i] = dl_state.dl_plus_tags[i].length_marker & 0x7F; -    } - -    // CRC -    dg->AppendCRC(); - -    return dg; -} - - -std::vector<std::string> split_string(const std::string &s, const char delimiter) { -    std::vector<std::string> result; -    std::stringstream ss(s); -    std::string part; - -    while (std::getline(ss, part, delimiter)) -        result.push_back(part); -    return result; -} - -bool parse_dl_param_bool(const std::string &key, const std::string &value, bool &target) { -    if (value == "0") { -        target = 0; -        return true; -    } -    if (value == "1") { -        target = 1; -        return true; -    } -    fprintf(stderr, "mot-encoder Warning: DL parameter '%s' has unsupported value '%s' - ignored\n", key.c_str(), value.c_str()); -    return false; -} - -bool parse_dl_param_int_dl_plus_tag(const std::string &key, const std::string &value, int &target) { -    int value_int = atoi(value.c_str()); -    if (value_int >= 0x00 && value_int <= 0x7F) { -        target = value_int; -        return true; -    } -    fprintf(stderr, "mot-encoder Warning: DL Plus tag parameter '%s' %d out of range - ignored\n", key.c_str(), value_int); -    return false; -} - -void parse_dl_params(std::ifstream &dls_fstream, DL_STATE &dl_state) { -    std::string line; -    while (std::getline(dls_fstream, line)) { -        // return on params close -        if (line == DL_PARAMS_CLOSE) -            return; - -        // ignore empty lines and comments -        if (line.empty() || line[0] == '#') -            continue; - -        // parse key/value pair -        size_t separator_pos = line.find('='); -        if (separator_pos == std::string::npos) { -            fprintf(stderr, "mot-encoder Warning: DL parameter line '%s' without separator - ignored\n", line.c_str()); -            continue; -        } -        std::string key = line.substr(0, separator_pos); -        std::string value = line.substr(separator_pos + 1); -#if DEBUG -        fprintf(stderr, "parse_dl_params: key: '%s', value: '%s'\n", key.c_str(), value.c_str()); -#endif - -        if (key == "DL_PLUS") { -            parse_dl_param_bool(key, value, dl_state.dl_plus_enabled); -            continue; -        } -        if (key == "DL_PLUS_ITEM_TOGGLE") { -            parse_dl_param_bool(key, value, dl_state.dl_plus_item_toggle); -            continue; -        } -        if (key == "DL_PLUS_ITEM_RUNNING") { -            parse_dl_param_bool(key, value, dl_state.dl_plus_item_running); -            continue; -        } -        if (key == "DL_PLUS_TAG") { -            if (dl_state.dl_plus_tags.size() == 4) { -                fprintf(stderr, "mot-encoder Warning: DL Plus tag ignored, as already four tags present\n"); -                continue; -            } - -            // split value -            std::vector<std::string> params = split_string(value, ' '); -            if (params.size() != 3) { -                fprintf(stderr, "mot-encoder Warning: DL Plus tag value '%s' does not have three parts - ignored\n", value.c_str()); -                continue; -            } - -            int content_type, start_marker, length_marker; -            if (parse_dl_param_int_dl_plus_tag("content_type", params[0], content_type) & -                parse_dl_param_int_dl_plus_tag("start_marker", params[1], start_marker) & -                parse_dl_param_int_dl_plus_tag("length_marker", params[2], length_marker)) -                dl_state.dl_plus_tags.push_back(DL_PLUS_TAG(content_type, start_marker, length_marker)); -            continue; -        } - -        fprintf(stderr, "mot-encoder Warning: DL parameter '%s' unknown - ignored\n", key.c_str()); -    } - -    fprintf(stderr, "mot-encoder Warning: no param closing tag, so the DLS text will be empty\n"); -} - - -void writeDLS(int output_fd, const std::string& dls_file, uint8_t charset, bool raw_dls, bool remove_dls) -{ -    std::ifstream dls_fstream(dls_file); -    if (!dls_fstream.is_open()) { -        std::cerr << "Could not open " << dls_file << std::endl; -        return; -    } - -    DL_STATE dl_state; - -    std::vector<std::string> dls_lines; - -    std::string line; -    // Read and convert lines one by one because the converter doesn't understand -    // line endings -    while (std::getline(dls_fstream, line)) { -        if (line.empty()) -            continue; -        if (line == DL_PARAMS_OPEN) { -            parse_dl_params(dls_fstream, dl_state); -        } else { -            if (not raw_dls && charset == CHARSET_UTF8) { -                dls_lines.push_back(charset_converter.convert(line)); -            } -            else { -                dls_lines.push_back(line); -            } -            // TODO handle the other charsets accordingly -        } -    } - -    std::stringstream ss; -    for (size_t i = 0; i < dls_lines.size(); i++) { -        if (i != 0) { -            if (charset == CHARSET_UCS2_BE) -                ss << '\0' << '\n'; -            else -                ss << '\n'; -        } - -        // UCS-2 BE: if from file the first byte of \0\n remains, remove it -        if (charset == CHARSET_UCS2_BE && dls_lines[i].size() % 2) { -            dls_lines[i].resize(dls_lines[i].size() - 1); -        } - -        ss << dls_lines[i]; -    } - -    dl_state.dl_text = ss.str(); -    if (dl_state.dl_text.size() > MAXDLS) -        dl_state.dl_text.resize(MAXDLS); - - -    // if DL Plus enabled, but no DL Plus tags were added, add the required DUMMY tag -    if (dl_state.dl_plus_enabled && dl_state.dl_plus_tags.empty()) -        dl_state.dl_plus_tags.push_back(DL_PLUS_TAG()); - -    if (not raw_dls) -        charset = CHARSET_COMPLETE_EBU_LATIN; - - -    // toggle the toggle bit only on new DL state -    bool dl_state_is_new = dl_state != dl_state_prev; -    if (verbose) { -        fprintf(stderr, "mot-encoder writing %s DLS text \"%s\"\n", dl_state_is_new ? "new" : "old", dl_state.dl_text.c_str()); -        if (dl_state.dl_plus_enabled) { -            fprintf( -                    stderr, "mot-encoder writing %s DL Plus tags (IT/IR: %d/%d): ", -                    dl_state_is_new ? "new" : "old", -                    dl_state.dl_plus_item_toggle ? 1 : 0, -                    dl_state.dl_plus_item_running ? 1 : 0); -            for (dl_plus_tags_t::const_iterator it = dl_state.dl_plus_tags.begin(); it != dl_state.dl_plus_tags.end(); it++) { -                if (it != dl_state.dl_plus_tags.begin()) -                    fprintf(stderr, ", "); -                fprintf(stderr, "%d (S/L: %d/%d)", it->content_type, it->start_marker, it->length_marker); -            } -            fprintf(stderr, "\n"); -        } -    } - -    DATA_GROUP *remove_label_dg = NULL; -    if (dl_state_is_new) { -        if (remove_dls) -            remove_label_dg = createDynamicLabelCommand(DLS_CMD_REMOVE_LABEL); - -        dls_toggle = !dls_toggle;   // indicate changed text - -        dl_state_prev = dl_state; -    } - -    prepend_dl_dgs(dl_state, charset); -    if (remove_label_dg) -        pad_packetizer->queue.push_front(remove_label_dg); -    pad_packetizer->WriteAllPADs(output_fd); -} - - -int dls_count(const std::string& text) { -    size_t text_len = text.size(); -    return text_len / DLS_SEG_LEN_CHAR_MAX + (text_len % DLS_SEG_LEN_CHAR_MAX ? 1 : 0); -} - - -DATA_GROUP* dls_get(const std::string& text, uint8_t charset, int seg_index) { -    bool first_seg = seg_index == 0; -    bool last_seg  = seg_index == dls_count(text) - 1; - -    int seg_text_offset = seg_index * DLS_SEG_LEN_CHAR_MAX; -    const char *seg_text_start = text.c_str() + seg_text_offset; -    size_t seg_text_len = MIN(text.size() - seg_text_offset, DLS_SEG_LEN_CHAR_MAX); - -    DATA_GROUP* dg = new DATA_GROUP(DLS_SEG_LEN_PREFIX + seg_text_len, 2, 3); -    uint8_vector_t &seg_data = dg->data; - -    // prefix: toggle? + first seg? + last seg? + (seg len - 1) -    seg_data[0] = -            (dls_toggle ? (1 << 7) : 0) + -            (first_seg  ? (1 << 6) : 0) + -            (last_seg   ? (1 << 5) : 0) + -            (seg_text_len - 1); - -    // prefix: charset / seg index -    seg_data[1] = (first_seg ? charset : seg_index) << 4; - -    // character field -    memcpy(&seg_data[DLS_SEG_LEN_PREFIX], seg_text_start, seg_text_len); - -    // CRC -    dg->AppendCRC(); - -#if DEBUG -    fprintf(stderr, "DL segment:"); -    for (int i = 0; i < seg_data.size(); i++) -        fprintf(stderr, " %02x", seg_data[i]); -    fprintf(stderr, "\n"); -#endif -    return dg; -} - - -void prepend_dl_dgs(const DL_STATE& dl_state, uint8_t charset) { -    // process all DL segments -    int seg_count = dls_count(dl_state.dl_text); -    std::vector<DATA_GROUP*> segs; -    for (int seg_index = 0; seg_index < seg_count; seg_index++) { -#if DEBUG -        fprintf(stderr, "Segment number %d\n", seg_index + 1); -#endif -        segs.push_back(dls_get(dl_state.dl_text, charset, seg_index)); -    } - -    // if enabled, add DL Plus data group -    if (dl_state.dl_plus_enabled) -        segs.push_back(createDynamicLabelPlus(dl_state)); - -    // prepend to packetizer -    pad_packetizer->queue.insert(pad_packetizer->queue.begin(), segs.begin(), segs.end()); - -#if DEBUG -    fprintf(stderr, "PAD length: %d\n", padlen); -    fprintf(stderr, "DLS text: %s\n", text.c_str()); -    fprintf(stderr, "Number of DL segments: %d\n", seg_count); -#endif -} - -int History::find(const fingerprint_t& fp) const -{ -    size_t i; -    for (i = 0; i < m_database.size(); i++) { -        if (m_database[i] == fp) { -            // return the id of fingerprint found -            return m_database[i].fidx; -        } -    } - -    // return -1 when the database doesn't contain this fingerprint -    return -1; -} - -void History::add(fingerprint_t& fp) -{ -    m_database.push_back(fp); - -    if (m_database.size() > m_hist_size) { -        m_database.pop_front(); -    } -} - -void History::disp_database() -{ -    size_t id; -    printf("HISTORY DATABASE:\n"); -    if (m_database.empty()) { -        printf(" empty\n"); -    } -    else { -        for (id = 0; id < m_database.size(); id++) { -            printf(" id %4zu: ", id); -            m_database[id].disp(); -        } -    } -    printf("-----------------\n"); -} - -int History::get_fidx(const char* filepath) -{ -    fingerprint_t fp; - -    fp.load_from_file(filepath); - -    int idx = find(fp); - -    if (idx < 0) { -        idx = m_last_given_fidx++; -        fp.fidx = idx; - -        if (m_last_given_fidx > MAXSLIDEID) { -            m_last_given_fidx = 0; -        } - -        add(fp); -    } - -    return idx; -} - diff --git a/src/utf8.h b/src/utf8.h deleted file mode 100644 index 4e44514..0000000 --- a/src/utf8.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2006 Nemanja Trifunovic
 -
 -/*
 -Permission is hereby granted, free of charge, to any person or organization
 -obtaining a copy of the software and accompanying documentation covered by
 -this license (the "Software") to use, reproduce, display, distribute,
 -execute, and transmit the Software, and to prepare derivative works of the
 -Software, and to permit third-parties to whom the Software is furnished to
 -do so, all subject to the following:
 -
 -The copyright notices in the Software and this entire statement, including
 -the above license grant, this restriction and the following disclaimer,
 -must be included in all copies of the Software, in whole or in part, and
 -all derivative works of the Software, unless such copies or derivative
 -works are solely in the form of machine-executable object code generated by
 -a source language processor.
 -
 -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
 -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
 -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
 -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 -DEALINGS IN THE SOFTWARE.
 -*/
 -
 -
 -#ifndef UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
 -#define UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
 -
 -#include "utf8/checked.h"
 -#include "utf8/unchecked.h"
 -
 -#endif // header guard
 diff --git a/src/utf8/checked.h b/src/utf8/checked.h deleted file mode 100644 index 1331155..0000000 --- a/src/utf8/checked.h +++ /dev/null @@ -1,327 +0,0 @@ -// Copyright 2006 Nemanja Trifunovic - -/* -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -*/ - - -#ifndef UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 -#define UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 - -#include "core.h" -#include <stdexcept> - -namespace utf8 -{ -    // Base for the exceptions that may be thrown from the library -    class exception : public ::std::exception { -    }; - -    // Exceptions that may be thrown from the library functions. -    class invalid_code_point : public exception { -        uint32_t cp; -    public: -        invalid_code_point(uint32_t cp) : cp(cp) {} -        virtual const char* what() const throw() { return "Invalid code point"; } -        uint32_t code_point() const {return cp;} -    }; - -    class invalid_utf8 : public exception { -        uint8_t u8; -    public: -        invalid_utf8 (uint8_t u) : u8(u) {} -        virtual const char* what() const throw() { return "Invalid UTF-8"; } -        uint8_t utf8_octet() const {return u8;} -    }; - -    class invalid_utf16 : public exception { -        uint16_t u16; -    public: -        invalid_utf16 (uint16_t u) : u16(u) {} -        virtual const char* what() const throw() { return "Invalid UTF-16"; } -        uint16_t utf16_word() const {return u16;} -    }; - -    class not_enough_room : public exception { -    public: -        virtual const char* what() const throw() { return "Not enough space"; } -    }; - -    /// The library API - functions intended to be called by the users - -    template <typename octet_iterator> -    octet_iterator append(uint32_t cp, octet_iterator result) -    { -        if (!utf8::internal::is_code_point_valid(cp)) -            throw invalid_code_point(cp); - -        if (cp < 0x80)                        // one octet -            *(result++) = static_cast<uint8_t>(cp); -        else if (cp < 0x800) {                // two octets -            *(result++) = static_cast<uint8_t>((cp >> 6)            | 0xc0); -            *(result++) = static_cast<uint8_t>((cp & 0x3f)          | 0x80); -        } -        else if (cp < 0x10000) {              // three octets -            *(result++) = static_cast<uint8_t>((cp >> 12)           | 0xe0); -            *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f)   | 0x80); -            *(result++) = static_cast<uint8_t>((cp & 0x3f)          | 0x80); -        } -        else {                                // four octets -            *(result++) = static_cast<uint8_t>((cp >> 18)           | 0xf0); -            *(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f)  | 0x80); -            *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f)   | 0x80); -            *(result++) = static_cast<uint8_t>((cp & 0x3f)          | 0x80); -        } -        return result; -    } - -    template <typename octet_iterator, typename output_iterator> -    output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement) -    { -        while (start != end) { -            octet_iterator sequence_start = start; -            internal::utf_error err_code = utf8::internal::validate_next(start, end); -            switch (err_code) { -                case internal::UTF8_OK : -                    for (octet_iterator it = sequence_start; it != start; ++it) -                        *out++ = *it; -                    break; -                case internal::NOT_ENOUGH_ROOM: -                    throw not_enough_room(); -                case internal::INVALID_LEAD: -                    out = utf8::append (replacement, out); -                    ++start; -                    break; -                case internal::INCOMPLETE_SEQUENCE: -                case internal::OVERLONG_SEQUENCE: -                case internal::INVALID_CODE_POINT: -                    out = utf8::append (replacement, out); -                    ++start; -                    // just one replacement mark for the sequence -                    while (start != end && utf8::internal::is_trail(*start)) -                        ++start; -                    break; -            } -        } -        return out; -    } - -    template <typename octet_iterator, typename output_iterator> -    inline output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out) -    { -        static const uint32_t replacement_marker = utf8::internal::mask16(0xfffd); -        return utf8::replace_invalid(start, end, out, replacement_marker); -    } - -    template <typename octet_iterator> -    uint32_t next(octet_iterator& it, octet_iterator end) -    { -        uint32_t cp = 0; -        internal::utf_error err_code = utf8::internal::validate_next(it, end, cp); -        switch (err_code) { -            case internal::UTF8_OK : -                break; -            case internal::NOT_ENOUGH_ROOM : -                throw not_enough_room(); -            case internal::INVALID_LEAD : -            case internal::INCOMPLETE_SEQUENCE : -            case internal::OVERLONG_SEQUENCE : -                throw invalid_utf8(*it); -            case internal::INVALID_CODE_POINT : -                throw invalid_code_point(cp); -        } -        return cp; -    } - -    template <typename octet_iterator> -    uint32_t peek_next(octet_iterator it, octet_iterator end) -    { -        return utf8::next(it, end); -    } - -    template <typename octet_iterator> -    uint32_t prior(octet_iterator& it, octet_iterator start) -    { -        // can't do much if it == start -        if (it == start) -            throw not_enough_room(); - -        octet_iterator end = it; -        // Go back until we hit either a lead octet or start -        while (utf8::internal::is_trail(*(--it))) -            if (it == start) -                throw invalid_utf8(*it); // error - no lead byte in the sequence -        return utf8::peek_next(it, end); -    } - -    /// Deprecated in versions that include "prior" -    template <typename octet_iterator> -    uint32_t previous(octet_iterator& it, octet_iterator pass_start) -    { -        octet_iterator end = it; -        while (utf8::internal::is_trail(*(--it))) -            if (it == pass_start) -                throw invalid_utf8(*it); // error - no lead byte in the sequence -        octet_iterator temp = it; -        return utf8::next(temp, end); -    } - -    template <typename octet_iterator, typename distance_type> -    void advance (octet_iterator& it, distance_type n, octet_iterator end) -    { -        for (distance_type i = 0; i < n; ++i) -            utf8::next(it, end); -    } - -    template <typename octet_iterator> -    typename std::iterator_traits<octet_iterator>::difference_type -    distance (octet_iterator first, octet_iterator last) -    { -        typename std::iterator_traits<octet_iterator>::difference_type dist; -        for (dist = 0; first < last; ++dist) -            utf8::next(first, last); -        return dist; -    } - -    template <typename u16bit_iterator, typename octet_iterator> -    octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result) -    { -        while (start != end) { -            uint32_t cp = utf8::internal::mask16(*start++); -            // Take care of surrogate pairs first -            if (utf8::internal::is_lead_surrogate(cp)) { -                if (start != end) { -                    uint32_t trail_surrogate = utf8::internal::mask16(*start++); -                    if (utf8::internal::is_trail_surrogate(trail_surrogate)) -                        cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET; -                    else -                        throw invalid_utf16(static_cast<uint16_t>(trail_surrogate)); -                } -                else -                    throw invalid_utf16(static_cast<uint16_t>(cp)); - -            } -            // Lone trail surrogate -            else if (utf8::internal::is_trail_surrogate(cp)) -                throw invalid_utf16(static_cast<uint16_t>(cp)); - -            result = utf8::append(cp, result); -        } -        return result; -    } - -    template <typename u16bit_iterator, typename octet_iterator> -    u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result) -    { -        while (start != end) { -            uint32_t cp = utf8::next(start, end); -            if (cp > 0xffff) { //make a surrogate pair -                *result++ = static_cast<uint16_t>((cp >> 10)   + internal::LEAD_OFFSET); -                *result++ = static_cast<uint16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN); -            } -            else -                *result++ = static_cast<uint16_t>(cp); -        } -        return result; -    } - -    template <typename octet_iterator, typename u32bit_iterator> -    octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result) -    { -        while (start != end) -            result = utf8::append(*(start++), result); - -        return result; -    } - -    template <typename octet_iterator, typename u32bit_iterator> -    u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result) -    { -        while (start != end) -            (*result++) = utf8::next(start, end); - -        return result; -    } - -    // The iterator class -    template <typename octet_iterator> -    class iterator : public std::iterator <std::bidirectional_iterator_tag, uint32_t> { -      octet_iterator it; -      octet_iterator range_start; -      octet_iterator range_end; -      public: -      iterator () {} -      explicit iterator (const octet_iterator& octet_it, -                         const octet_iterator& range_start, -                         const octet_iterator& range_end) : -               it(octet_it), range_start(range_start), range_end(range_end) -      { -          if (it < range_start || it > range_end) -              throw std::out_of_range("Invalid utf-8 iterator position"); -      } -      // the default "big three" are OK -      octet_iterator base () const { return it; } -      uint32_t operator * () const -      { -          octet_iterator temp = it; -          return utf8::next(temp, range_end); -      } -      bool operator == (const iterator& rhs) const -      { -          if (range_start != rhs.range_start || range_end != rhs.range_end) -              throw std::logic_error("Comparing utf-8 iterators defined with different ranges"); -          return (it == rhs.it); -      } -      bool operator != (const iterator& rhs) const -      { -          return !(operator == (rhs)); -      } -      iterator& operator ++ () -      { -          utf8::next(it, range_end); -          return *this; -      } -      iterator operator ++ (int) -      { -          iterator temp = *this; -          utf8::next(it, range_end); -          return temp; -      } -      iterator& operator -- () -      { -          utf8::prior(it, range_start); -          return *this; -      } -      iterator operator -- (int) -      { -          iterator temp = *this; -          utf8::prior(it, range_start); -          return temp; -      } -    }; // class iterator - -} // namespace utf8 - -#endif //header guard - - diff --git a/src/utf8/core.h b/src/utf8/core.h deleted file mode 100644 index 693d388..0000000 --- a/src/utf8/core.h +++ /dev/null @@ -1,329 +0,0 @@ -// Copyright 2006 Nemanja Trifunovic - -/* -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -*/ - - -#ifndef UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 -#define UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 - -#include <iterator> - -namespace utf8 -{ -    // The typedefs for 8-bit, 16-bit and 32-bit unsigned integers -    // You may need to change them to match your system. -    // These typedefs have the same names as ones from cstdint, or boost/cstdint -    typedef unsigned char   uint8_t; -    typedef unsigned short  uint16_t; -    typedef unsigned int    uint32_t; - -// Helper code - not intended to be directly called by the library users. May be changed at any time -namespace internal -{ -    // Unicode constants -    // Leading (high) surrogates: 0xd800 - 0xdbff -    // Trailing (low) surrogates: 0xdc00 - 0xdfff -    const uint16_t LEAD_SURROGATE_MIN  = 0xd800u; -    const uint16_t LEAD_SURROGATE_MAX  = 0xdbffu; -    const uint16_t TRAIL_SURROGATE_MIN = 0xdc00u; -    const uint16_t TRAIL_SURROGATE_MAX = 0xdfffu; -    const uint16_t LEAD_OFFSET         = LEAD_SURROGATE_MIN - (0x10000 >> 10); -    const uint32_t SURROGATE_OFFSET    = 0x10000u - (LEAD_SURROGATE_MIN << 10) - TRAIL_SURROGATE_MIN; - -    // Maximum valid value for a Unicode code point -    const uint32_t CODE_POINT_MAX      = 0x0010ffffu; - -    template<typename octet_type> -    inline uint8_t mask8(octet_type oc) -    { -        return static_cast<uint8_t>(0xff & oc); -    } -    template<typename u16_type> -    inline uint16_t mask16(u16_type oc) -    { -        return static_cast<uint16_t>(0xffff & oc); -    } -    template<typename octet_type> -    inline bool is_trail(octet_type oc) -    { -        return ((utf8::internal::mask8(oc) >> 6) == 0x2); -    } - -    template <typename u16> -    inline bool is_lead_surrogate(u16 cp) -    { -        return (cp >= LEAD_SURROGATE_MIN && cp <= LEAD_SURROGATE_MAX); -    } - -    template <typename u16> -    inline bool is_trail_surrogate(u16 cp) -    { -        return (cp >= TRAIL_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX); -    } - -    template <typename u16> -    inline bool is_surrogate(u16 cp) -    { -        return (cp >= LEAD_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX); -    } - -    template <typename u32> -    inline bool is_code_point_valid(u32 cp) -    { -        return (cp <= CODE_POINT_MAX && !utf8::internal::is_surrogate(cp)); -    } - -    template <typename octet_iterator> -    inline typename std::iterator_traits<octet_iterator>::difference_type -    sequence_length(octet_iterator lead_it) -    { -        uint8_t lead = utf8::internal::mask8(*lead_it); -        if (lead < 0x80) -            return 1; -        else if ((lead >> 5) == 0x6) -            return 2; -        else if ((lead >> 4) == 0xe) -            return 3; -        else if ((lead >> 3) == 0x1e) -            return 4; -        else -            return 0; -    } - -    template <typename octet_difference_type> -    inline bool is_overlong_sequence(uint32_t cp, octet_difference_type length) -    { -        if (cp < 0x80) { -            if (length != 1)  -                return true; -        } -        else if (cp < 0x800) { -            if (length != 2)  -                return true; -        } -        else if (cp < 0x10000) { -            if (length != 3)  -                return true; -        } - -        return false; -    } - -    enum utf_error {UTF8_OK, NOT_ENOUGH_ROOM, INVALID_LEAD, INCOMPLETE_SEQUENCE, OVERLONG_SEQUENCE, INVALID_CODE_POINT}; - -    /// Helper for get_sequence_x -    template <typename octet_iterator> -    utf_error increase_safely(octet_iterator& it, octet_iterator end) -    { -        if (++it == end) -            return NOT_ENOUGH_ROOM; - -        if (!utf8::internal::is_trail(*it)) -            return INCOMPLETE_SEQUENCE; -         -        return UTF8_OK; -    } - -    #define UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(IT, END) {utf_error ret = increase_safely(IT, END); if (ret != UTF8_OK) return ret;}     - -    /// get_sequence_x functions decode utf-8 sequences of the length x -    template <typename octet_iterator> -    utf_error get_sequence_1(octet_iterator& it, octet_iterator end, uint32_t& code_point) -    { -        if (it == end) -            return NOT_ENOUGH_ROOM; - -        code_point = utf8::internal::mask8(*it); - -        return UTF8_OK; -    } - -    template <typename octet_iterator> -    utf_error get_sequence_2(octet_iterator& it, octet_iterator end, uint32_t& code_point) -    { -        if (it == end)  -            return NOT_ENOUGH_ROOM; -         -        code_point = utf8::internal::mask8(*it); - -        UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) - -        code_point = ((code_point << 6) & 0x7ff) + ((*it) & 0x3f); - -        return UTF8_OK; -    } - -    template <typename octet_iterator> -    utf_error get_sequence_3(octet_iterator& it, octet_iterator end, uint32_t& code_point) -    { -        if (it == end) -            return NOT_ENOUGH_ROOM; -             -        code_point = utf8::internal::mask8(*it); - -        UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) - -        code_point = ((code_point << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff); - -        UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) - -        code_point += (*it) & 0x3f; - -        return UTF8_OK; -    } - -    template <typename octet_iterator> -    utf_error get_sequence_4(octet_iterator& it, octet_iterator end, uint32_t& code_point) -    { -        if (it == end) -           return NOT_ENOUGH_ROOM; - -        code_point = utf8::internal::mask8(*it); - -        UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) - -        code_point = ((code_point << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff); - -        UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) - -        code_point += (utf8::internal::mask8(*it) << 6) & 0xfff; - -        UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) - -        code_point += (*it) & 0x3f; - -        return UTF8_OK; -    } - -    #undef UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR - -    template <typename octet_iterator> -    utf_error validate_next(octet_iterator& it, octet_iterator end, uint32_t& code_point) -    { -        // Save the original value of it so we can go back in case of failure -        // Of course, it does not make much sense with i.e. stream iterators -        octet_iterator original_it = it; - -        uint32_t cp = 0; -        // Determine the sequence length based on the lead octet -        typedef typename std::iterator_traits<octet_iterator>::difference_type octet_difference_type; -        const octet_difference_type length = utf8::internal::sequence_length(it); - -        // Get trail octets and calculate the code point -        utf_error err = UTF8_OK; -        switch (length) { -            case 0:  -                return INVALID_LEAD; -            case 1: -                err = utf8::internal::get_sequence_1(it, end, cp); -                break; -            case 2: -                err = utf8::internal::get_sequence_2(it, end, cp); -            break; -            case 3: -                err = utf8::internal::get_sequence_3(it, end, cp); -            break; -            case 4: -                err = utf8::internal::get_sequence_4(it, end, cp); -            break; -        } - -        if (err == UTF8_OK) { -            // Decoding succeeded. Now, security checks... -            if (utf8::internal::is_code_point_valid(cp)) { -                if (!utf8::internal::is_overlong_sequence(cp, length)){ -                    // Passed! Return here. -                    code_point = cp; -                    ++it; -                    return UTF8_OK; -                } -                else -                    err = OVERLONG_SEQUENCE; -            } -            else  -                err = INVALID_CODE_POINT; -        } - -        // Failure branch - restore the original value of the iterator -        it = original_it; -        return err; -    } - -    template <typename octet_iterator> -    inline utf_error validate_next(octet_iterator& it, octet_iterator end) { -        uint32_t ignored; -        return utf8::internal::validate_next(it, end, ignored); -    } - -} // namespace internal - -    /// The library API - functions intended to be called by the users - -    // Byte order mark -    const uint8_t bom[] = {0xef, 0xbb, 0xbf}; - -    template <typename octet_iterator> -    octet_iterator find_invalid(octet_iterator start, octet_iterator end) -    { -        octet_iterator result = start; -        while (result != end) { -            utf8::internal::utf_error err_code = utf8::internal::validate_next(result, end); -            if (err_code != internal::UTF8_OK) -                return result; -        } -        return result; -    } - -    template <typename octet_iterator> -    inline bool is_valid(octet_iterator start, octet_iterator end) -    { -        return (utf8::find_invalid(start, end) == end); -    } - -    template <typename octet_iterator> -    inline bool starts_with_bom (octet_iterator it, octet_iterator end) -    { -        return ( -            ((it != end) && (utf8::internal::mask8(*it++)) == bom[0]) && -            ((it != end) && (utf8::internal::mask8(*it++)) == bom[1]) && -            ((it != end) && (utf8::internal::mask8(*it))   == bom[2]) -           ); -    } -	 -    //Deprecated in release 2.3  -    template <typename octet_iterator> -    inline bool is_bom (octet_iterator it) -    { -        return ( -            (utf8::internal::mask8(*it++)) == bom[0] && -            (utf8::internal::mask8(*it++)) == bom[1] && -            (utf8::internal::mask8(*it))   == bom[2] -           ); -    } -} // namespace utf8 - -#endif // header guard - - diff --git a/src/utf8/unchecked.h b/src/utf8/unchecked.h deleted file mode 100644 index cb24271..0000000 --- a/src/utf8/unchecked.h +++ /dev/null @@ -1,228 +0,0 @@ -// Copyright 2006 Nemanja Trifunovic - -/* -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -*/ - - -#ifndef UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 -#define UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 - -#include "core.h" - -namespace utf8 -{ -    namespace unchecked  -    { -        template <typename octet_iterator> -        octet_iterator append(uint32_t cp, octet_iterator result) -        { -            if (cp < 0x80)                        // one octet -                *(result++) = static_cast<uint8_t>(cp);   -            else if (cp < 0x800) {                // two octets -                *(result++) = static_cast<uint8_t>((cp >> 6)          | 0xc0); -                *(result++) = static_cast<uint8_t>((cp & 0x3f)        | 0x80); -            } -            else if (cp < 0x10000) {              // three octets -                *(result++) = static_cast<uint8_t>((cp >> 12)         | 0xe0); -                *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80); -                *(result++) = static_cast<uint8_t>((cp & 0x3f)        | 0x80); -            } -            else {                                // four octets -                *(result++) = static_cast<uint8_t>((cp >> 18)         | 0xf0); -                *(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f)| 0x80); -                *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80); -                *(result++) = static_cast<uint8_t>((cp & 0x3f)        | 0x80); -            } -            return result; -        } - -        template <typename octet_iterator> -        uint32_t next(octet_iterator& it) -        { -            uint32_t cp = utf8::internal::mask8(*it); -            typename std::iterator_traits<octet_iterator>::difference_type length = utf8::internal::sequence_length(it); -            switch (length) { -                case 1: -                    break; -                case 2: -                    it++; -                    cp = ((cp << 6) & 0x7ff) + ((*it) & 0x3f); -                    break; -                case 3: -                    ++it;  -                    cp = ((cp << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff); -                    ++it; -                    cp += (*it) & 0x3f; -                    break; -                case 4: -                    ++it; -                    cp = ((cp << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff);                 -                    ++it; -                    cp += (utf8::internal::mask8(*it) << 6) & 0xfff; -                    ++it; -                    cp += (*it) & 0x3f;  -                    break; -            } -            ++it; -            return cp;         -        } - -        template <typename octet_iterator> -        uint32_t peek_next(octet_iterator it) -        { -            return utf8::unchecked::next(it);     -        } - -        template <typename octet_iterator> -        uint32_t prior(octet_iterator& it) -        { -            while (utf8::internal::is_trail(*(--it))) ; -            octet_iterator temp = it; -            return utf8::unchecked::next(temp); -        } - -        // Deprecated in versions that include prior, but only for the sake of consistency (see utf8::previous) -        template <typename octet_iterator> -        inline uint32_t previous(octet_iterator& it) -        { -            return utf8::unchecked::prior(it); -        } - -        template <typename octet_iterator, typename distance_type> -        void advance (octet_iterator& it, distance_type n) -        { -            for (distance_type i = 0; i < n; ++i) -                utf8::unchecked::next(it); -        } - -        template <typename octet_iterator> -        typename std::iterator_traits<octet_iterator>::difference_type -        distance (octet_iterator first, octet_iterator last) -        { -            typename std::iterator_traits<octet_iterator>::difference_type dist; -            for (dist = 0; first < last; ++dist)  -                utf8::unchecked::next(first); -            return dist; -        } - -        template <typename u16bit_iterator, typename octet_iterator> -        octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result) -        {        -            while (start != end) { -                uint32_t cp = utf8::internal::mask16(*start++); -            // Take care of surrogate pairs first -                if (utf8::internal::is_lead_surrogate(cp)) { -                    uint32_t trail_surrogate = utf8::internal::mask16(*start++); -                    cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET; -                } -                result = utf8::unchecked::append(cp, result); -            } -            return result;          -        } - -        template <typename u16bit_iterator, typename octet_iterator> -        u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result) -        { -            while (start < end) { -                uint32_t cp = utf8::unchecked::next(start); -                if (cp > 0xffff) { //make a surrogate pair -                    *result++ = static_cast<uint16_t>((cp >> 10)   + internal::LEAD_OFFSET); -                    *result++ = static_cast<uint16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN); -                } -                else -                    *result++ = static_cast<uint16_t>(cp); -            } -            return result; -        } - -        template <typename octet_iterator, typename u32bit_iterator> -        octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result) -        { -            while (start != end) -                result = utf8::unchecked::append(*(start++), result); - -            return result; -        } - -        template <typename octet_iterator, typename u32bit_iterator> -        u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result) -        { -            while (start < end) -                (*result++) = utf8::unchecked::next(start); - -            return result; -        } - -        // The iterator class -        template <typename octet_iterator> -          class iterator : public std::iterator <std::bidirectional_iterator_tag, uint32_t> {  -            octet_iterator it; -            public: -            iterator () {} -            explicit iterator (const octet_iterator& octet_it): it(octet_it) {} -            // the default "big three" are OK -            octet_iterator base () const { return it; } -            uint32_t operator * () const -            { -                octet_iterator temp = it; -                return utf8::unchecked::next(temp); -            } -            bool operator == (const iterator& rhs) const  -            {  -                return (it == rhs.it); -            } -            bool operator != (const iterator& rhs) const -            { -                return !(operator == (rhs)); -            } -            iterator& operator ++ ()  -            { -                ::std::advance(it, utf8::internal::sequence_length(it)); -                return *this; -            } -            iterator operator ++ (int) -            { -                iterator temp = *this; -                ::std::advance(it, utf8::internal::sequence_length(it)); -                return temp; -            }   -            iterator& operator -- () -            { -                utf8::unchecked::prior(it); -                return *this; -            } -            iterator operator -- (int) -            { -                iterator temp = *this; -                utf8::unchecked::prior(it); -                return temp; -            } -          }; // class iterator - -    } // namespace utf8::unchecked -} // namespace utf8  - - -#endif // header guard - | 
