VideoTools
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
gbase64.cpp
Go to the documentation of this file.
1 //
2 // Copyright (C) 2017 Graeme Walker
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 // ===
17 //
18 // gbase64.cpp
19 //
20 
21 #include "gdef.h"
22 #include "gbase64.h"
23 #include "gassert.h"
24 #include "gstr.h"
25 #include <cstring>
26 
27 namespace
28 {
29  const char * character_map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" ;
30  char pad = '=' ;
31 }
32 
33 g_uint32_t G::Base64::numeric( char c )
34 {
35  return static_cast<g_uint32_t>( static_cast<unsigned char>(c) ) ;
36 }
37 
38 void G::Base64::accumulate_8( g_uint32_t & n , std::string::const_iterator & p ,
39  std::string::const_iterator end , int & i )
40 {
41  char c = p == end ? '\0' : *p ;
42  n <<= 8U ;
43  n |= numeric(c) ;
44  if( p != end )
45  {
46  ++p ;
47  ++i ;
48  }
49 }
50 
51 size_t G::Base64::hi_6( g_uint32_t n )
52 {
53  return (n >> 18U) & 0x3F ;
54 }
55 
56 void G::Base64::generate_6( g_uint32_t & n , int & i , std::string & result )
57 {
58  char c = i-- >= 0 ? character_map[hi_6(n)] : pad ;
59  result.append( 1U , c ) ;
60  n <<= 6U ;
61 }
62 
63 std::string G::Base64::encode( const std::string & s_in )
64 {
65  return encode( s_in , "\015\012" ) ;
66 }
67 
68 std::string G::Base64::encode( const std::string & s_in , const std::string & eol )
69 {
70  std::string result ;
71  size_t blocks = 0U ;
72  for( std::string::const_iterator p = s_in.begin() ; p != s_in.end() ; blocks++ )
73  {
74  if( blocks && (blocks % 19U) == 0U )
75  result.append( eol ) ;
76 
77  g_uint32_t n = 0UL ;
78  int i = 0 ;
79  accumulate_8( n , p , s_in.end() , i ) ;
80  accumulate_8( n , p , s_in.end() , i ) ;
81  accumulate_8( n , p , s_in.end() , i ) ;
82  generate_6( n , i , result ) ;
83  generate_6( n , i , result ) ;
84  generate_6( n , i , result ) ;
85  generate_6( n , i , result ) ;
86  }
87 
88  return result ;
89 }
90 
91 // ---
92 
93 char G::Base64::to_char( g_uint32_t n )
94 {
95  return static_cast<char>(static_cast<unsigned char>(n)) ;
96 }
97 
98 size_t G::Base64::index( char c , bool & error )
99 {
100  const char * p = std::strchr( character_map , c ) ;
101  error = error || !c || !p ;
102  if( p == nullptr )
103  return 0U ;
104  else
105  return static_cast<size_t>( p - character_map ) ;
106 }
107 
108 size_t G::Base64::accumulate_6( g_uint32_t & n , char c_in , int & n_out , bool & error )
109 {
110  n <<= 6U ;
111  if( c_in != pad )
112  {
113  n |= index(c_in,error) ;
114  n_out++ ;
115  }
116  return c_in != '\0' ;
117 }
118 
119 g_uint32_t G::Base64::hi_8( g_uint32_t n )
120 {
121  return (n >> 16U) & 0xff ;
122 }
123 
124 void G::Base64::generate_8( g_uint32_t & n , int & n_out , std::string & result )
125 {
126  if( n_out-- > 0 )
127  result.append( 1U , to_char(hi_8(n)) ) ;
128  n <<= 8U ;
129 }
130 
131 std::string G::Base64::decode( const std::string & s )
132 {
133  bool error = false ;
134  std::string result = decode( s , error ) ;
135  if( error )
136  throw Error() ;
137  return result ;
138 }
139 
140 std::string G::Base64::decode( const std::string & s , bool & error )
141 {
142  std::string result ;
143  for( const char * p = s.c_str() ; *p ; )
144  {
145  if( *p == '\r' || *p == '\n' )
146  {
147  p++ ;
148  continue ;
149  }
150 
151  g_uint32_t n = 0UL ;
152  size_t i = 0U ;
153  int n_out = -1 ;
154  i += accumulate_6( n , p[i] , n_out , error ) ;
155  i += accumulate_6( n , p[i] , n_out , error ) ;
156  i += accumulate_6( n , p[i] , n_out , error ) ;
157  i += accumulate_6( n , p[i] , n_out , error ) ;
158  p += i ;
159  generate_8( n , n_out , result ) ;
160  generate_8( n , n_out , result ) ;
161  generate_8( n , n_out , result ) ;
162  }
163  return result ;
164 }
165 
166 bool G::Base64::valid( const std::string & s )
167 {
168  bool error = false ;
169  std::string result = decode( s , error ) ; G_IGNORE_VARIABLE(result) ;
170  return !error ;
171 }
172 
173 /// \file gbase64.cpp
static bool valid(const std::string &)
Returns true if the string can be decoded.
Definition: gbase64.cpp:166
static std::string decode(const std::string &)
Decodes the given string.
Definition: gbase64.cpp:131
static std::string encode(const std::string &s, const std::string &line_break)
Encodes the given string.
Definition: gbase64.cpp:68