public key in HEX format to EC_KEY using c++ - c++

I have a public key in hex format in c++ code. I have to convert this public key to EC_KEY structure which is used by openssl to verify the signature. The problem is that I am not able to convert hex string to pem format from which openssl can generate the public key.
Tried:
1. I convert the hex string to bytes. (I guess this converts to ascii format)
2. this byte string to converted to base64 (ascii format to base64 encoding)
3. use PEM_read_bio_EC_PUBKEY to get the public key (read as pem)
4. EC_KEY_check_key fails.
static const char b64_table[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static std::string base64_encode(const ::std::string& bindata)
{
using ::std::string;
using ::std::numeric_limits;
if (bindata.size() > ((numeric_limits<string::size_type>::max)() / 4u) * 3u)
{
throw ::std::length_error("Converting too large a string to base64.");
}
const ::std::size_t binlen = bindata.size();
// Use = signs so the end is properly padded.
string retval((((binlen + 2) / 3) * 4), '=');
::std::size_t outpos = 0;
int bits_collected = 0;
unsigned int accumulator = 0;
const string::const_iterator binend = bindata.end();
for (string::const_iterator i = bindata.begin(); i != binend; ++i) {
accumulator = (accumulator << 8) | (*i & 0xffu);
bits_collected += 8;
while (bits_collected >= 6) {
bits_collected -= 6;
retval[outpos++] = b64_table[(accumulator >> bits_collected) & 0x3fu];
}
}
if (bits_collected > 0) { // Any trailing bits that are missing.
assert(bits_collected < 6);
accumulator <<= 6 - bits_collected;
retval[outpos++] = b64_table[accumulator & 0x3fu];
}
assert(outpos >= (retval.size() - 2));
assert(outpos <= retval.size());
return retval;
}
std::string HexToBytes(const std::string& hex)
{
std::string bytes;
for (unsigned int i = 0; i < hex.length(); i += 2) {
std::string byteString = hex.substr(i, 2);
char byte = (char)strtol(byteString.c_str(), NULL, 16);
bytes.push_back(byte);
}
return bytes;
}
int main(int argc, char* argv[])
{
// Set up the public key....
std::string sPubKeyString = "E3A7E51FE102286D071026111088F680761FDCD7031E3D56244BBE07451601E78AD08AD40EADCF380900985A1FAB94DE6D02DB91920F1144E9EBC4E248444969";
std::string sKeyInAscii = HexToBytes(sPubKeyString);
std::string sPub64(base64_encode(sKeyInAscii));
std::string sKeyInPem = std::string("-----BEGIN PUBLIC KEY-----\n") + sPub64 + std::string("\n-----END PUBLIC KEY-----");
const char* pzKey = sKeyInPem.c_str();
std::unique_ptr< BIO, std::function<void(BIO*)>> bo(BIO_new(BIO_s_mem()), [](BIO* b) { BIO_free(b); });
BIO_write(bo.get(), pzKey, strlen(pzKey));
std::unique_ptr< EC_KEY, std::function<void(EC_KEY*)>> zPublicKey(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1), [](EC_KEY* b) { EC_KEY_free(b); });
EC_KEY* pPubKey = zPublicKey.get();
PEM_read_bio_EC_PUBKEY(bo.get(), &pPubKey, NULL, NULL);
if (EC_KEY_check_key(pPubKey) == 1) {
printf("EC Key valid.\n");
}
else {
printf("EC Key Invalid!\n");
}
}
This code prints EC Key Invalid. I dont know what wrong I am doing. Thanks in advance

Related

Custom lua bytecode / opcode (compiler / reader / parser / decompiler)

01/02/05/70/72/69/6E/74/01/68/01/02/00/00/01/06/A3/00/00/00/A4/00/01/00/00/00/00/40/6F/01/02/00/9F/00/02/01/82/00/01/00/03/03/01/04/00/00/00/40/03/02/00/00/06/01/00/00/00/00/00/00/00 is bytecode for
print"h"
I need a way to make a compiler that can turn any bytecode into a semi accurate script.
I've already made one but its very bad and it only supports the Clouse, getglobal, setglobal, loadk, loadnil, loadnumber, loadbool, call, gettablek, clearstack, init, vararg, return and length. Most of the time it will come out wrong..
Code:
#include <iostream>
#include <Windows.h>
#include <string>
#include <sstream>
#include <algorithm>
#include <iterator>
#include <vector>
namespace opcodes {
std::string GETGLOBAL = "A4";
std::string SETGLOBAL = "18";
std::string GETTABLEK = "4D";
std::string SETTABLEK = "30";
std::string LOADK = "6F";
std::string RETURN = "82";
std::string LOADNUMBER = "8C";
std::string CALL = "9F";
std::string CLEARSTACK = "A3";
std::string LOADBOOL = "A9";
std::string LOADNIL = "C6";
std::string CLOSURE = "D9";
std::string INIT = "C0";
std::string LEN = "1C";
std::string SUB = "26";
std::string FORLOOP = "8B";
std::string FORPREP = "A8";
std::string VARARG = "DD";
std::string SETUPVAL = "DE";
};
std::vector<std::string> FuncsGlob;
std::vector<std::string> locals;
std::stringstream ss;
std::string inp = "";
std::vector<std::string> hexs;
std::string script;
std::string Value;
std::string lf = "";
std::string HTA(std::string hex)
{
// initialize the ASCII code string as empty.
std::string ascii = "";
for (size_t i = 0; i < hex.length(); i += 2)
{
// extract two characters from hex string
std::string part = hex.substr(i, 2);
// change it into base 16 and
// typecast as the character
char ch = stoul(part, nullptr, 16);
// add this char to final ASCII string
ascii += ch;
}
return ascii;
}
void Split(const std::string& s, char c,
std::vector<std::string>& v) {
std::string::size_type i = 0;
std::string::size_type j = s.find(c);
while (j != std::string::npos) {
v.push_back(s.substr(i, j - i));
i = ++j;
j = s.find(c, j);
if (j == std::string::npos)
v.push_back(s.substr(i, s.length()));
}
}
static bool isF(std::string func) {
std::vector<std::string> funcs = {"wait", "warn", "print"};
for (int i = 0; i < funcs.size(); i++)
{
if (funcs[i] == func)
{
return true;
}
}
return false;
}
int main()
{
std::cout << "Enter bytecode: ";
inp = "01/02/05/70/72/69/6E/74/01/68/01/02/00/00/01/06/A3/00/00/00/A4/00/01/00/00/00/00/40/6F/01/02/00/9F/00/02/01/82/00/01/00/03/03/01/04/00/00/00/40/03/02/00/00/06/01/00/00/00/00/00/00/00";
std::cout << std::endl;
Split(inp, '/', hexs);
if (hexs[0] == "01") {
int stringtables = std::stoi(hexs[1]);
int FSize = 2;
std::string ValueName;
int psr = 1;
int clsr = 0;
int init = 0;
int conv = 0;
int lk_r = 0;
int slitthroat = 0;
int b_s = std::stoi(hexs[FSize]);
for (unsigned int sti = 0; sti < stringtables; sti++) {
for (int cur = FSize + psr; cur < FSize + b_s + 1; cur++) {
ValueName = (std::string)HTA((std::string)hexs[cur]);
Value += ValueName;
conv = cur;
}
psr++;
b_s = std::stoi(hexs[conv + 1]) + 1;
FSize = conv++;
FuncsGlob.insert(FuncsGlob.end(), Value);
Value = "";
ValueName = "";
}
for (int nig = conv; nig < hexs.size(); ++nig) {
locals.resize(hexs.size() + 1);
FuncsGlob.resize(hexs.size() + 1);
if (hexs[nig] == opcodes::LOADK) {
script += "\"" + FuncsGlob[lk_r] + "\"";
slitthroat++;
lk_r++;
}
if (hexs[nig] == opcodes::GETGLOBAL) {
if (isF(FuncsGlob[lk_r]))
script += FuncsGlob[lk_r] + "(";
else
script += FuncsGlob[lk_r] + ".";
lk_r++;
}
if (hexs[nig] == opcodes::CALL) {
if (clsr == 0) {
if (script[script.length() - 1] == '.')
script = script.erase(script.length() - 1);
script += ")";
}
}
if (hexs[nig] == opcodes::CLEARSTACK) {
lk_r = 0;
}
if (hexs[nig] == opcodes::GETTABLEK) {
script += FuncsGlob[lk_r] + ".";
lk_r++;
}
if (hexs[nig] == opcodes::LOADNUMBER) {
script += std::stoi(hexs[nig + 2]);
}
if (hexs[nig] == opcodes::LOADBOOL) {
if (hexs[nig + 2] == "00") {
script += "false";
}
else if (hexs[nig + 2] == "01") {
script += "true";
}
}
if (hexs[nig] == opcodes::LOADNIL) {
script += "nil";
}
if (hexs[nig] == opcodes::INIT) {
init++;
}
if (hexs[nig] == opcodes::CLOSURE) {
if (init > 0) {
script = "(function() " + script + "end)()";
init--;
clsr++;
}
else {
script = "(function() " + script + "end)";
clsr++;
}
}
if (hexs[nig] == opcodes::RETURN) {
clsr = 0;
}
if (hexs[nig] == opcodes::VARARG) {
script += "...";
}
if (hexs[nig] == opcodes::LEN) {
script += "#";
}
}
std::cout << std::endl << script;
}
}

How should I parse and check through a string?

Okay so I have a C++ project I want to complete which involves receiving NMEA sentences and parsing through them to check if they conform to the "grammar rules" of NMEA.
The current method I have been doing this is using if statements but this is obviously not good coding practice.
What are other methods I could use to attempt to check string sentences for specific characters and groups of characters?
Let us assume that you have NMEA data like this
$GPGGA,124613.90,5543.3221231,N,03739.1368442,E,1,15,0.69,147.0851,M,14.4298,M,,*54
$GPGSV,3,1,10,27,12,078,41,05,31,308,49,16,25,043,44,02,11,268,44*7E
$GPGSV,3,2,10,26,03,031,39,07,74,216,52,09,58,121,52,30,39,234,48*71
$GPGSV,3,3,10,23,30,116,46,04,37,114,47*79
$GLGSV,2,1,07,84,17,338,43,78,15,212,48,85,12,032,46,67,84,223,53*67
$GLGSV,2,2,07,77,67,195,47,76,50,047,54,66,32,144,52*5C
$GPGGA,124614.00,5543.3221239,N,03739.1368445,E,1,15,0.69,147.0864,M,14.4298,M,,*53
$GPGSV,3,1,10,27,12,078,41,05,31,308,49,16,25,043,43,02,11,268,44*79
$GPGSV,3,2,10,26,03,031,39,07,74,216,52,09,58,121,52,30,39,234,48*71
$GPGSV,3,3,10,23,30,116,46,04,37,114,47*79
$GLGSV,2,1,07,84,17,338,43,78,15,212,48,85,12,032,46,67,84,223,53*67
$GLGSV,2,2,07,77,67,195,47,76,50,047,54,66,32,144,52*5C
And if we want to extract GGA and GSV data, you may want to use the following code:
#include <string>
#include <ctime>
#include <cstring>
#include <iostream>
#include <fstream>
#include <iomanip>
constexpr size_t NumberOfFixQualityStrings = 9;
constexpr size_t NumberOfSatellitesPerGSVSentencePart = 4;
constexpr size_t MaxNumberOfPartsInSentence = 10;
constexpr size_t MaxTokensInSentence = 64;
constexpr size_t NumberOfFieldsInGGA = 12;
std::string fixQualityString[NumberOfFixQualityStrings]{
"invalid", "GPS fix (SPS)", "DGPS fix", "PPS fix", "Real Time Kinematic", "Float RTK",
"estimated (dead reckoning", "Manual input mode", "Simulation mode" };
// essential fix data which provide 3D location and accuracy data
struct GGA {
// Time of last satellite fix
unsigned int fixTimeInUtcHours{};
unsigned int fixTimeInUtcMinutes{};
unsigned int fixTimeInUtcSeconds{};
unsigned int fixTimeInUtcMilliSeconds{};
// Position: Lattitude
unsigned int lattitudeInDegree{};
double lattitudeInMinutes{};
std::string lattitideDirection{};
// Position: Longitude
unsigned int longitudeInDegree{};
double longitudeInMinutes{};
std::string longitudeDirection{};
// FixQuality // see dteails as string above
unsigned int fixQuality{};
std::string fixQualityString{};
// Number of satellites being tracked (can be more than shown in GSV, not all are beeing used for calculation)
unsigned int numberOfTrackedSatellites{};
// Horizontal dilution of position
double horizontalDilution{};
// Altitude, Meters, above mean sea level
double altitude{};
std::string altitudeDimension{};
// Height of geoid (mean sea level) above WGS84 ellipsoid
double goidHight{};
std::string goidHightDimension{};
};
// Detail information for satellites in satellit view (GSV)
struct SatelliteData {
std::string satellitePRNnumber{};
double elevationInDegress{};
double azimuthInDegrees{};
double snr{}; // signal noise ratio
};
// Part of a GSV sentence
struct GSVSentencePart {
size_t numberOfSentencesForFullData{};
size_t sentencePartNumber{};
size_t numberOfSatellitesInView{};
size_t numberOfSatellitesInThisPart{};
SatelliteData satelliteData[NumberOfSatellitesPerGSVSentencePart];
};
struct GSV
{
GSVSentencePart gsvSentencePart[MaxNumberOfPartsInSentence];
size_t numberOfParts{};
};
bool checksumTest(std::string& line) {
bool result{ false };
// Check, if there is a 2 digt checksum at the end and convert it to decimal
if (size_t pos{}, checkSumGiven{ std::stoul(line.substr(line.size() - 2), &pos, 16) }; pos == 2)
{
// Strip off checksum part
line = line.substr(1,line.size() - 4);
// Calculate checksum
unsigned char calculatedChecksum{ 0U }; for (const unsigned char c : line) calculatedChecksum ^= c;
// Get result
result = (calculatedChecksum == checkSumGiven);
}
return result;
}
// Split all strings into a tokens
size_t splitIntoTokens(std::string& s, std::string (&tokens)[MaxTokensInSentence]) {
// Number of converted tokens
size_t numberOfTokens{ 0 };
// First check checksum
if (checksumTest(s)) {
// Now split along each comma
for (size_t i{ 0U }, startpos{ 0U }; i < s.size(); ++i) {
// So, if there is a comma or the end of the string
if ((s[i] == ',') || (i == (s.size() - 1))) {
// Copy substring
tokens[numberOfTokens++] = s.substr(startpos, i - startpos);
startpos = i + 1;
}
}
}
return numberOfTokens;
}
GGA convertStringToGGA(std::string& s) {
GGA gga;
// Split string into tokens and check, if it worked
if (std::string tokens[MaxTokensInSentence]; splitIntoTokens(s, tokens) > NumberOfFieldsInGGA && tokens[0] == "GPGGA") {
gga.fixTimeInUtcHours = std::stoul(tokens[1].substr(0, 2));
gga.fixTimeInUtcMinutes = std::stoul(tokens[1].substr(2, 2));
gga.fixTimeInUtcSeconds = std::stoul(tokens[1].substr(4, 2));
gga.fixTimeInUtcMilliSeconds = std::stod(tokens[1].substr(6, 2))*1000.0;
gga.lattitudeInDegree = std::stoul(tokens[2].substr(0, 2));
gga.lattitudeInMinutes = std::stod(tokens[2].substr(2));
gga.lattitideDirection = tokens[3];
gga.longitudeInDegree = std::stoul(tokens[4].substr(0, 2));
gga.longitudeInMinutes = std::stod(tokens[4].substr(2));
gga.longitudeDirection = tokens[5];
gga.fixQuality = std::stoul(tokens[6]);
gga.fixQualityString = (gga.fixQuality < NumberOfFixQualityStrings) ? fixQualityString[gga.fixQuality] : fixQualityString[0];
gga.numberOfTrackedSatellites = std::stoul(tokens[7]);
gga.horizontalDilution = std::stod(tokens[8]);
gga.altitude = std::stod(tokens[9]);
gga.altitudeDimension = tokens[10];
gga.goidHight = std::stod(tokens[11]);
gga.goidHightDimension = tokens[12];
}
return gga;
}
GSVSentencePart convertToGSVSentencePart(std::string& s) {
GSVSentencePart gsvsp;
// Split string into tokens and check, if it worked
std::string tokens[MaxTokensInSentence];
if (size_t numberOfCOnvertedTokens = splitIntoTokens(s, tokens); numberOfCOnvertedTokens > 0 && tokens[0] == "GPGSV") {
gsvsp.numberOfSentencesForFullData = std::stoul(tokens[1]);
gsvsp.sentencePartNumber = std::stoul(tokens[2]);
gsvsp.numberOfSatellitesInView = std::stoul(tokens[3]);
gsvsp.numberOfSatellitesInThisPart = 0;
for (size_t currentToken = 4; currentToken < numberOfCOnvertedTokens; currentToken += 4) {
gsvsp.satelliteData[gsvsp.numberOfSatellitesInThisPart].satellitePRNnumber = tokens[currentToken];
gsvsp.satelliteData[gsvsp.numberOfSatellitesInThisPart].elevationInDegress = stod(tokens[currentToken + 1]);
gsvsp.satelliteData[gsvsp.numberOfSatellitesInThisPart].azimuthInDegrees= stod(tokens[currentToken + 2]);
gsvsp.satelliteData[gsvsp.numberOfSatellitesInThisPart].snr = stod(tokens[currentToken + 3]);
++gsvsp.numberOfSatellitesInThisPart;
}
}
return gsvsp;
}
std::string calculateElapsedTime(const GGA& previousGGA, const GGA& nextGGA) {
std::tm tmPrevious{}, tmNext{};
tmPrevious.tm_year = 100; tmPrevious.tm_mon = 1; tmPrevious.tm_mday = 1;
tmNext.tm_year = 100; tmNext.tm_mon = 1; tmNext.tm_mday = 1;
tmPrevious.tm_hour = previousGGA.fixTimeInUtcHours;
tmPrevious.tm_min = previousGGA.fixTimeInUtcMinutes;
tmPrevious.tm_sec = previousGGA.fixTimeInUtcSeconds;
std::time_t previousTime = std::mktime(&tmPrevious);
tmNext.tm_hour = nextGGA.fixTimeInUtcHours;
tmNext.tm_min = nextGGA.fixTimeInUtcMinutes;
tmNext.tm_sec = nextGGA.fixTimeInUtcSeconds;
std::time_t nextTime = std::mktime(&tmNext);
double diff = std::difftime(nextTime, previousTime);
diff = diff + 1.0*nextGGA.fixTimeInUtcMilliSeconds/1000.0- 1.0*previousGGA.fixTimeInUtcMilliSeconds/1000.0;
return std::to_string(diff);
}
int main() {
// Open file and check, if it is open
if (std::ifstream nmeaFile("r:\\log.txt"); nmeaFile) {
GGA previousGGA;
GGA nextGGA;
GSV gsv;
size_t state{ 0 };
for (std::string line{}; std::getline(nmeaFile, line); ) {
switch ( state) {
case 0: // wait for first GGA data
if (line.substr(0, 6) == "$GPGGA") {
previousGGA = nextGGA;
nextGGA = convertStringToGGA(line);
state = 1;
gsv = {};
}
break;
case 1: // wait for GSV
if (line.substr(0, 6) == "$GPGSV") {
gsv.gsvSentencePart[gsv.numberOfParts] = convertToGSVSentencePart(line);
if (gsv.gsvSentencePart[gsv.numberOfParts].numberOfSentencesForFullData ==
gsv.gsvSentencePart[gsv.numberOfParts].sentencePartNumber) {
state = 0;
++gsv.numberOfParts;
// Now all data are available in reable and structed format.
// You can do, what you want with them
// For example, we can print all Satellite Data:
size_t counter{ 0 };
for (size_t i = 0; i < gsv.numberOfParts; ++i) {
for (size_t j = 0; j < gsv.gsvSentencePart[i].numberOfSatellitesInThisPart; j++) {
std::cout << "Satellite: " << std::setw(2) << ++counter << " Satellite name: " <<
std::setw(3) << gsv.gsvSentencePart[i].satelliteData[j].satellitePRNnumber <<
" SNR: " << std::setw(8) << gsv.gsvSentencePart[i].satelliteData[j].snr <<
" Elapsed time: "<< calculateElapsedTime(previousGGA, nextGGA)<< " s\n";
}
}
--gsv.numberOfParts;
}
++gsv.numberOfParts;
}
break;
}
}
}
return 0;
}
Coding style is "beginner"-level for easier understanding.
Modern C++ approach would be totally different, but not so easy to understand.

Dictionary flush in LZW algorithm

I have compressor/decompressor for LZW.
Now i want to use custom variable(size) to keep dictionary size in bytes and then it becomes large enough i revert dictionary to initial state and start fill it again.
But i dont realize how to implement it. I had several tries.
First time i flushed dict then it had maxSize elements, however it may become to large.
Next time i increased size by size of new element in dict, but program
took several Gb from memory and broke everything at the end.
Coder
void lzwCodeFile(istream &in, ostream &out, uint32_t maxSize) {
unordered_map<string, uint32_t> mp;
clearAndFill(mp);
uint32_t code = 256;
uint32_t size = 256;
string w = "";
string tmp;
uint8_t c;
while (in.read((char *) &c, sizeof c)) {
tmp = w;
tmp += c;
if (mp.find(tmp) != mp.end()) {
w = tmp;
} else {
uint32_t val = mp[w];
out.write((const char *) &val, sizeof(mp[w]));
//cout << val << " ";
mp[tmp] = code++;
size += tmp.size();
w = c;
}
}
if (w.size()) {
uint32_t val = mp[w];
out.write((const char *) &val, sizeof(mp[w]));
//cout << val << " ";
}
}
Decoder
void lzwDecodeFile(istream &in, ostream &out, uint32_t maxSize) {
unordered_map<uint32_t, string> mp;
uint32_t code = 256;
uint32_t size = 256;
clearAndFillRev(mp);
string tmp, w;
uint32_t k;
in.read((char *) &k, sizeof k);
w = "" + mp[k];
string entry;
out << w;
while (in.read((char *) &k, sizeof k)) {
// finded
if (mp.find(k) != mp.end()) {
entry = mp[k];
} else {
entry = w + w[0];
}
out << entry;
tmp = w + entry[0];
mp[code++]=tmp;
w = entry;
}
}

Equivalent of wstring in C

How can I read and access Unicode characters with standard C. Previously I was using C++ and std::wstring for whole word and 'const wchar_t' for a single characters, which works perfectly( below is example code).
But now I am not allowed to use C++. How can I replace the 'wstring' in C? How can I convert my code to standard C?
...
...
const wchar_t small_char[10]={ L'锕',L'吖',L'啊',L'阿',L'呵',L'嗄',L'埃',L'哀',L'哎'};
std::wstring strIn=L"锕吖哎";
std::wstring s_temp=L"";
int length= strIn.length();
for(int i=0;i<length;i++){
if(strIn[i]==small_char[2]){
s_temp=s_temp+L"ba";
}
else if(strIn[i]==small_char[5]){
s_temp=s_temp+L"pe";
}
else{
s_temp=s_temp+strIn[i];
}
}
...
...
How can I replace the 'wstring' in C? How can I convert my code to standard C?
std::wstring is just a wrapper for wchar_t*. You can use wchar_t directly, you just have to manage the string memory and concatenations manually.
Try this:
...
const wchar_t small_char[10] = { L'锕', L'吖', L'啊', L'阿', L'呵', L'嗄', L'埃', L'哀', L'哎'};
wchar_t *strIn = L"锕吖哎";
int length = wcslen(strIn);
wchar_t *s_temp = (wchar_t*) calloc((length*2)+1, sizeof(wchar_t));
int s_temp_len = 0;
for(int i = 0; i < length; i++)
{
if (strIn[i] == small_char[2])
{
memcpy(&s_temp[s_temp_len], L"ba", 2*sizeof(wchar_t));
s_temp_len += 2;
s_temp[s_temp_len] = L'\0';
}
else if (strIn[i] == small_char[5])
{
memcpy(&s_temp[s_temp_len], L"pe", 2*sizeof(wchar_t));
s_temp_len += 2;
s_temp[s_temp_len] = L'\0';
}
else
{
s_temp[s_temp_len] = strIn[i];
s_temp_len += 1;
s_temp[s_temp_len] = L'\0';
}
}
// use s_temp up to s_temp_len characters as needed...
free(s_temp);
...
If you want something more like std::wstring, you should pre-allocate a small buffer and resize it whenever you are going to exceed its capacity during concatenations. A struct is useful for keeping track of that:
struct my_wstring
{
wchar_t *data;
int length;
int capacity;
};
void wstring_init(struct my_wstring *str)
{
str->data = NULL;
str->length = 0;
str->capacity = 0;
};
void wstring_clear(struct my_wstring *str)
{
free(str->data);
str->data = NULL;
str->length = 0;
str->capacity = 0;
};
// allocate in multiples of 32
const int delta = 32;
void wstring_append_str_len(struct my_wstring *str, const wchar_t *value, int valueLen)
{
if ((!str) || (!value) || (valueLen < 1)) return;
int newLen = str->length + valueLen;
if ((newLen + 1) > str->capacity)
{
// round to next highest multiple of 32
int newCap = ((newLen + 1) + (delta - 1)) & ~delta;
wchar_t *newData = (wchar_t*) realloc(str->data, newCap * sizeof(wchar_t));
if (!newData)
{
// memory allocation error, do something!
return;
}
str->data = newData;
str->capacity = newCap;
}
memcpy(&(str->data[str->length]), value, valueLen * sizeof(wchar_t));
str->length = newLen;
str->data[newLen] = L'\0';
}
void wstring_append_str(struct wstring *str, const wchar_t *value)
{
wstring_append_str_len(str, value, wcslen(value));
}
void wstring_append_chr(struct wstring *str, const wchar_t value)
{
wstring_append_str_len(str, &value, 1);
}
...
const wchar_t small_char[10] = { L'锕', L'吖', L'啊', L'阿', L'呵', L'嗄', L'埃', L'哀', L'哎'};
wchar_t *strIn = L"锕吖哎";
struct my_wstring s_temp;
wstring_init(&s_temp);
int length = wcslen(strIn);
for(int i = 0; i < length; i++)
{
if (strIn[i] == small_char[2])
{
wstring_append_str(&s_temp, L"ba");
}
else if (strIn[i] == small_char[5])
{
wstring_append_str(&s_temp, L"pe");
}
else
{
wstring_append_chr(&s_temp, strIn[i]);
}
}
// use s_temp.data up to s_temp.length characters as needed...
wstring_clear(&s_temp);
...
The equivalent C routines are
== wcscmp or wcsncmp
+= wcscat or wcscat_s
= wcscpy or wcsncpy or wcscpy_s
.size() or length() wcslen
In your case since you are comparing one character at a time, you do not need wcscmp. Make sure all your strings are null terminated otherwise the non _s versions won't work.

Encode/Decode URl In C++

How can i encode a URL in client side and Decode the same in Server side.Is there any Built in apis are available for this purpose.Please anyone suggest a solution.Also i want to know how can i do percentage encoding in C++?
I've found this implementation from dlib quite useful. You don't even need to grab the whole library, just these 4 functions (unhex, hex, encode, decode). And it has a boost license.
You can check out this article and this
Encode:
std::string UriEncode(const std::string & sSrc)
{
const char DEC2HEX[16 + 1] = "0123456789ABCDEF";
const unsigned char * pSrc = (const unsigned char *)sSrc.c_str();
const int SRC_LEN = sSrc.length();
unsigned char * const pStart = new unsigned char[SRC_LEN * 3];
unsigned char * pEnd = pStart;
const unsigned char * const SRC_END = pSrc + SRC_LEN;
for (; pSrc < SRC_END; ++pSrc)
{
if (SAFE[*pSrc])
*pEnd++ = *pSrc;
else
{
// escape this char
*pEnd++ = '%';
*pEnd++ = DEC2HEX[*pSrc >> 4];
*pEnd++ = DEC2HEX[*pSrc & 0x0F];
}
}
std::string sResult((char *)pStart, (char *)pEnd);
delete [] pStart;
return sResult;
}
Decode:
std::string UriDecode(const std::string & sSrc)
{
// Note from RFC1630: "Sequences which start with a percent
// sign but are not followed by two hexadecimal characters
// (0-9, A-F) are reserved for future extension"
const unsigned char * pSrc = (const unsigned char *)sSrc.c_str();
const int SRC_LEN = sSrc.length();
const unsigned char * const SRC_END = pSrc + SRC_LEN;
// last decodable '%'
const unsigned char * const SRC_LAST_DEC = SRC_END - 2;
char * const pStart = new char[SRC_LEN];
char * pEnd = pStart;
while (pSrc < SRC_LAST_DEC)
{
if (*pSrc == '%')
{
char dec1, dec2;
if (-1 != (dec1 = HEX2DEC[*(pSrc + 1)])
&& -1 != (dec2 = HEX2DEC[*(pSrc + 2)]))
{
*pEnd++ = (dec1 << 4) + dec2;
pSrc += 3;
continue;
}
}
*pEnd++ = *pSrc++;
}
// the last 2- chars
while (pSrc < SRC_END)
*pEnd++ = *pSrc++;
std::string sResult(pStart, pEnd);
delete [] pStart;
return sResult;
}
For Encoding:
You can use "g_uri_escape_string()" function provided glib.h.
https://developer.gnome.org/glib/stable/glib-URI-Functions.html
#include <stdio.h>
#include <stdlib.h>
#include <glib.h>
int main() {
char *uri = "http://www.example.com?hello world";
char *encoded_uri = NULL;
//as per wiki (https://en.wikipedia.org/wiki/Percent-encoding)
char *escape_char_str = "!*'();:#&=+$,/?#[]";
encoded_uri = g_uri_escape_string(uri, escape_char_str, TRUE);
printf("[%s]\n", encoded_uri);
free(encoded_uri);
return 0;
}
compile it with:
gcc encoding_URI.c `pkg-config --cflags --libs glib-2.0`