I have a little problem to solve (sfml librairy).
void loadTexture::chargeTexture(string name){
map<string, const unsigned char* > myMap = {
{ "balle", balle},
{ "truc", truc }
};
if(texture.loadFromMemory(myMap["balle"], sizeof(myMap["balle"]))){
std::cout<< "image ok"<<std::endl;
}
}
This first code don't loadFromMemory but without compilation error (Failed to load image from memory. Reason: Corrupt PNG)
but this is ok.
void loadTexture::chargeTexture(string name){
map<string, const unsigned char* > myMap = {
{ "balle", balle},
{ "truc", truc }
};
if(texture.loadFromMemory(balle, sizeof(balle))){
std::cout<< "image ok"<<std::endl;
}
}
I don't know why the loading works from the const, but none from the map. (for this demo I don't use the param (string name) of the function just to be clear for you.
texture is declared before as a Texture of course.
You do not show us the type declaration of balle. I guess it is an array. Therefore sizeof(balle) is the size of the whole array.
The std::map stores only the pointer to the first byte of balle:
sizeof(myMap["balle"]) == sizeof(const unsigned char*), which is the size of the pointer which is 8 bytes on 64 bit architecture.
Solution:: You have to store the first byte and the size of the image into your map. You may use std::span, or std::string_view for this.
Or just use a pair with pointer and size:
void loadTexture::chargeTexture(string name){
map<string, pair<const unsigned char*, size_t> > myMap = {
{ "balle", {balle, sizeof(balle)} },
{ "truc", {truc, sizeof(truc)} }
};
const pair<const unsigned char*, size_t> &img = myMap["balle"];
if(texture.loadFromMemory(img.first, img.second)){
std::cout<< "image ok"<<std::endl;
}
}
Related
I have a Postgres function returning the type tp_m_info which contains
an array of pairs (see below). And I'm using libpqxx to connecting to
Postgres.
CREATE TYPE public.tp_m_set_id AS
(
m_id integer,
m_name text
);
CREATE TYPE public.tp_m_info AS
(
m_id integer,
m_name text,
m_value double precision,
m_is_true boolean,
original_ms tp_m_set_id[]
);
I can read int, double, str and even Boolean from the result:
iter[m_id].as<int>()
iter[m_name].c_str()
iter[m_value].as<double>()
// and bool like
std::string tmp_str = iter["m_is_true"].c_str();
if ("t" == tmp_str)
{
info.m_is_merged = true;
}
else
{
info.m_is_merged = false;
}
but I don't know how to handle "tp_m_set_id[]"
It failed with something like "std::vector<std::pair<uint32_t, std::string>>"
iter[original_ms].as<std::vector<std::pair<uint32_t, std::string>>>()
Any Idea how to get it?
In "libpq" there is binary resultFormat with:
PQexecParams() and paramFormats=1
see: https://www.postgresql.org/docs/10/libpq-exec.html
Is there a binary Format in "libpqxx" now? Has something changed in
the last 10 years?
see: http://pqxx.org/development/libpqxx/wiki/BinaryTransfers
Is there a fast way to get a block of compound data from libpqxx and
convert it to C++?
I guess the solution is
e.g. to use:
std::pair<int, int> my_pair = row["m_ints"].as<std::pair<int, int> >();
write into strconv.hxx:
template<> struct PQXX_LIBEXPORT string_traits<std::pair<int, int> >
{
static constexpr const char *name() noexcept { return "std::pair<int, int>"; }
static constexpr bool has_null() noexcept { return false; }
static bool is_null(std::pair<int, int>) { return false; }
[[noreturn]] static std::pair<int, int> null()
{ internal::throw_null_conversion(name()); }
static void from_string(const char Str[], std::pair<int, int> &Obj);
static std::string to_string(std::pair<int, int> Obj);
};
and in strconv.cxx implement:
static void from_string(const char Str[], std::pair &Obj);
static std::string to_string(std::pair Obj);
now you have to recompile libpqxx.
The problem is, the implementation of "from_string" ends up in stringparsing a string like "(9,5)". And Stringparsing is not what i want.
so i'm going to try libpq.
So I have the following available:
struct data_t {
char field1[10];
char field2[20];
char field3[30];
};
const char *getData(const char *key);
const char *field_keys[] = { "key1", "key2", "key3" };
This code is given to my and I cannot modify it in any way. It comes from some old C project.
I need to fill in the struct using the getData function with the different keys, something like the following:
struct data_t my_data;
strncpy(my_data.field1, getData(field_keys[0]), sizeof(my_data.field1));
strncpy(my_data.field1, getData(field_keys[1]), sizeof(my_data.field2));
strncpy(my_data.field1, getData(field_keys[2]), sizeof(my_data.field3));
Of course, this is a simplification, and more things are going on in each assignment. The point is that I would like to represent the mapping between keys and struct member in a constant structure, and use that to transform the last code in a loop. I am looking for something like the following:
struct data_t {
char field1[10];
char field2[20];
char field3[30];
};
typedef char *(data_t:: *my_struct_member);
const std::vector<std::pair<const char *, my_struct_member>> mapping = {
{ "FIRST_KEY" , &my_struct_t::field1},
{ "SECOND_KEY", &my_struct_t::field2},
{ "THIRD_KEY", &my_struct_t::field3},
};
int main()
{
data_t data;
for (auto const& it : mapping) {
strcpy(data.*(it.second), getData(it.first));
// Ideally, I would like to do
// strlcpy(data.*(it.second), getData(it.first), <the right sizeof here>);
}
}
This, however, has two problems:
It does not compile :) But I believe that should be easy to solve.
I am not sure about how to get the sizeof() argument for using strncpy/strlcpy, instead of strcpy. I am using char * as the type of the members, so I am losing the type information about how long each array is. In the other hand, I am not sure how to use the specific char[T] types of each member, because if each struct member pointer has a different type I don't think I will be able to have them in a std::vector<T>.
As explained in my comment, if you can store enough information to process a field in a mapping, then you can write a function that does the same.
Therefore, write a function to do so, using array references to ensure what you do is safe, e.g.:
template <std::size_t N>
void process_field(char (&dest)[N], const char * src)
{
strlcpy(dest, getData(src), N);
// more work with the field...
};
And then simply, instead of your for loop:
process_field(data.field1, "foo");
process_field(data.field2, "bar");
// ...
Note that the amount of lines is the same as with a mapping (one per field), so this is not worse than a mapping solution in terms of repetition.
Now, the advantages:
Easier to understand.
Faster: no memory needed to keep the mapping, more easily optimizable, etc.
Allows you to write different functions for different fields, easily, if needed.
Further, if both of your strings are known at compile-time, you can even do:
template <std::size_t N, std::size_t M>
void process_field(char (&dest)[N], const char (&src)[M])
{
static_assert(N >= M);
std::memcpy(dest, src, M);
// more work with the field...
};
Which will be always safe, e.g.:
process_field(data.field1, "123456789"); // just fits!
process_field(data.field1, "1234567890"); // error
Which has even more pros:
Way faster than any strcpy variant (if the call is done in run-time).
Guaranteed to be safe at compile-time instead of run-time.
A variadic templates based solution:
struct my_struct_t {
char one_field[30];
char another_field[40];
};
template<typename T1, typename T2>
void do_mapping(T1& a, T2& b) {
std::cout << sizeof(b) << std::endl;
strncpy(b, a, sizeof(b));
}
template<typename T1, typename T2, typename... Args>
void do_mapping(T1& a, T2& b, Args&... args) {
do_mapping(a, b);
do_mapping(args...);
}
int main()
{
my_struct_t ms;
do_mapping(
"FIRST_MAPPING", ms.one_field,
"SECOND_MAPPING", ms.another_field
);
return 0;
}
Since data_t is a POD structure, you can use offsetof() for this.
const std::vector<std::pair<const char *, std::size_t>> mapping = {
{ "FIRST_FIELD" , offsetof(data_t, field1},
{ "SECOND_FIELD", offsetof(data_t, field2)}
};
Then the loop would be:
for (auto const& it : mapping) {
strcpy(static_cast<char*>(&data) + it.second, getData(it.first));
}
I don't think there's any way to get the size of the member similarly. You can subtract the offset of the current member from the next member, but this will include padding bytes. You'd also have to special-case the last member, subtracting the offset from the size of the structure itself, since there's no next member.
The mapping can be a function to write the data into the appropriate member
struct mapping_t
{
const char * name;
std::function<void(my_struct_t *, const char *)> write;
};
const std::vector<mapping_t> mapping = {
{ "FIRST_KEY", [](data_t & data, const char * str) { strlcpy(data.field1, str, sizeof(data.field1); } }
{ "SECOND_KEY", [](data_t & data, const char * str) { strlcpy(data.field2, str, sizeof(data.field2); } },
{ "THIRD_KEY", [](data_t & data, const char * str) { strlcpy(data.field3, str, sizeof(data.field3); } },
};
int main()
{
data_t data;
for (auto const& it : mapping) {
it.write(data, getData(it.name));
}
}
To iterate over struct member you need:
offset / pointer to the beginning of that member
size of that member
struct Map {
const char *key;
std::size_t offset;
std::size_t size;
};
std::vector<Map> map = {
{ field_keys[0], offsetof(data_t, field1), sizeof(data_t::field1), },
{ field_keys[1], offsetof(data_t, field2), sizeof(data_t::field2), },
{ field_keys[2], offsetof(data_t, field3), sizeof(data_t::field3), },
};
once we have that we need strlcpy:
std::size_t mystrlcpy(char *to, const char *from, std::size_t max)
{
char * const to0 = to;
if (max == 0)
return 0;
while (--max != 0 && *from) {
*to++ = *from++;
}
*to = '\0';
return to0 - to - 1;
}
After having that, we can just:
data_t data;
for (auto const& it : map) {
mystrlcpy(reinterpret_cast<char*>(&data) + it.offset, getData(it.key), it.size);
}
That reinterpret_cast looks a bit ugly, but it just shift &data pointer to the needed field.
We can also create a smarter container which takes variable pointer on construction, thus is bind with an existing variable and it needs a little bit of writing:
struct Map2 {
static constexpr std::size_t max = sizeof(field_keys)/sizeof(*field_keys);
Map2(data_t* pnt) : mpnt(pnt) {}
char* getDest(std::size_t num) {
std::array<char*, max> arr = {
mpnt->field1,
mpnt->field2,
mpnt->field3,
};
return arr[num];
}
const char* getKey(std::size_t num) {
return field_keys[num];
}
std::size_t getSize(std::size_t num) {
std::array<std::size_t, max> arr = {
sizeof(mpnt->field1),
sizeof(mpnt->field2),
sizeof(mpnt->field3),
};
return arr[num];
}
private:
data_t* mpnt;
};
But probably makes the iterating more readable:
Map2 m(&data);
for (std::size_t i = 0; i < m.max; ++i) {
mystrlcpy(m.getDest(i), getData(m.getKey(i)), m.getSize(i));
}
Live code available at onlinegdb.
I have a simple class with one attribute std::unique_ptr<unsigned char[]> in C++. I want to have a function that converts string to std::unique_ptr<unsigned char[]>, other to convert float to std::unique_ptr<unsigned char[]>, and a third to return the attribute std::unique_ptr<unsigned char[]>. My header is compiling but the source CPP is not. Even the return attribute is not compiling.
#include <memory>
class SkinnyBuffer {
private:
std::unique_ptr<unsigned char[]> _buff;
public:
~SkinnyBuffer();
SkinnyBuffer();
void setBuffValue(float f);
void setBuffValue(std::string str);
std::unique_ptr<unsigned char[]>* getBuffValue();
};
#include "utils/SkinnyBuffer.h"
SkinnyBuffer::~SkinnyBuffer() { }
SkinnyBuffer::SkinnyBuffer() { }
void SkinnyBuffer::setBuffValue(float f) {
// How to implement it
_buff = f;
}
void SkinnyBuffer::setBuffValue(std::string str) {
_buff = std::unique_ptr<unsigned char[]>(str.data(), str.data() + str.length());
}
std::unique_ptr<unsigned char[]>* SkinnyBuffer::getBuffValue() {
return &_buff;
}
std::unique_ptr is a non-copyable object. If you need a read-only access to it, you have two (main) options:
Return a reference to unique_ptr itself:
const std::unique_ptr<unsigned char[]>& getBuffValue() const
{
return _buff;
}
Return a const pointer to the managed array:
const unsigned char* getBuffValue() const
{
return _buff.get();
}
To assign a string to the buffer, you can do:
void setBuffValue(const std::string& str)
{
_buff = std::make_unique<unsigned char []>(str.length() + 1);
std::copy_n(str.c_str(), str.length() + 1, _buff.get());
}
Note that you have to copy the terminating null character to your buffer. Otherwise it will be almost useless for the outside world because its length will not be known to the user.
But do you really need std::unique_ptr<unsigned char[]>? std::vector seems to be more appropriate here.
You cannot do it this way. You have to copy the content of the string in a new array that is pointed by the unique pointer and then return the unique pointer.
The other option is to return a string in your two inherited classes.
Return a view of the data in buff_, don't try to copy it.
const unsigned char * SkinnyBuffer::getBuffValue() const {
return _buff.get();
}
You can use that value until the SkinnyBuffer is destroyed or modified.
I have a custom class as a key in a map. When I try to insert an item into the map, the program terminates. There has to be a problem with the creation of the key.
class MyKey {
char* data;
bool operator<(const MyKey& s) const {
for(int i = 0; i < (int)(sizeof(data)/sizeof(char)); i++) {
if(data[i] > s.data[i])
return false;
}
return true;
}
}
map<MyKey, char>* map = new map<MyKey, char>;
MyKey* key = new MyKey(...);
map->insert(make_pair(*key, '0'));
The program terminates at the insert.
You can't determine the size of an array from the pointer alone like you're attempting to-do in the for-loop of your operator< function ... You will have to, at some point, pass in the size of the array that is being pointed to by data so that you don't overflow the bounds of the array data is pointing to. Since data is a pointer, sizeof(data) simply returns the size of a pointer on your platform, not the size of the array being pointed to by data.
For C++, rather than using an allocated array, you should possibily use a STL container that you can directly query for the size of the container object ... this could include std::string if it's string-data, or std::vector<unsigned char> if it's just a bunch of binary bytes.
The following works and prints A.
#include <iostream>
#include <map>
using namespace std;
class Key
{
public:
Key(int x):data(x) {}
bool operator<(const Key &k) const { return(data < k.data); }
private:
int data;
};
int main()
{
Key myKey(10);
map<Key, char> m;
m.insert(make_pair(myKey, 'A'));
map<Key, char>::iterator it = m.find(myKey);
if (it != m.end())
{
cout << (*it).second << endl;
}
}
From your example code, the operator < would not be called because you only insert one element in the map. And you said you don't implement a copy constructor. So following code would be a problem:
class MyKey {
public:
MyKey()
{
data = new char[10];
}
~MyKey()
{
delete data;
}
private:
char* data;
};
I have a struct:
typedef struct
{
int nNum;
string str;
}KeyPair;
Let's say I initialize my struct:
KeyPair keys[] =
{ {0, "tester"},
{2, "yadah"},
{0, "tester"}
};
I want to use the initialized values in a function. How do I pass this array struct as a function parameter?
I have:
FetchKeys( KeyPair *pKeys)
{
//get the contents of keys[] here...
}
How about?
template<int N> void FetchKeys(KeyPair const (&r)[N]){}
EDIT 2:
Or even
template<int N> void FetchKeys(KeyPair const (*p)[N])
with the call as
FetchKeys(&keys);
You can do it as #MSalters mentioned, or you can create a std::vector<KeyPair> and pass it to the function. Here is a sample code:
using namespace std;
struct KeyPair
{
int nNum;
string str;
};
void fetchKeys(const vector<KeyPair>& keys)
{
//Go through elements of the vector
vector<KeyPair>::const_iterator iter = keys.begin();
for(; iter != keys.end(); ++iter)
{
const KeyPair& pair = *iter;
}
}
int main()
{
KeyPair keys[] = {{0, "tester"},
{2, "yadah"},
{0, "tester"}
};
//Create a vector out of the array you are having
vector<KeyPair> v(keys, keys + sizeof(keys)/sizeof(keys[0]));
//Pass this vector to the function. This is safe as vector knows
//how many element it contains
fetchKeys(v);
return 0;
}
Should be
// Definition
void FetchKeys( KeyPair *pKeys, int nKeys)
{
//get the contents of keys[] here...
}
// Call
FetchKeys(keys, sizeof(keys)/sizeof(keys[0]));
In c/c++ the name of the array (of any type) represents the address of the first element of the array, so
keys and &keys [0] are same.
You can pass any one of them for KeyPair*.
You just callFetchKeys(keys);
EDIT
Pay attention to declare FetchKeys' return type.
EDIT 2
If you also need the number of items, you add size as FetchKeys input parameters:
void FetchKeys(KeyPair*, size_t size);
and call FetchKeys(keys, sizeof(keys)/sizeof(*keys));
BTW, state all your question by editing your first post if you can.
Depending on what you want to do you can even use boost range and pass it to function as a pair of iterators:
void FetchKeys(KeyPair *begin, KeyPair *end)
FetchKeys(boost::begin(keys), boost::end(keys));
See this answer: How can I pass an array by reference to a function in C++?
Wrap it in a structure, nice and easy..
#include <iostream>
struct foo
{
int a;
int b;
};
template <typename _T, size_t _size>
struct array_of
{
static size_t size() { return _size; }
_T data[_size];
};
template <typename _at>
void test(_at & array)
{
cout << "size: " << _at::size() << std::endl;
}
int main(void)
{
array_of<foo, 3> a = {{ {1,2}, {2,2}, {3,2} }};
test(a);
}
EDIT: URGH, I can't see the toolbar to format the code correctly, hopefully the tags works..
i use VS 2008, and this works fine for me.
#include "stdafx.h"
typedef struct
{
int nNum;
CString str;
}KeyPair;
void FetchKeys( KeyPair *pKeys);
int _tmain(int argc, _TCHAR* argv[])
{
KeyPair keys[] =
{ {0, _T("tester")},
{2, _T("yadah")},
{0, _T("tester")}
};
FetchKeys(keys); //--> just pass the initialized variable.
return 0;
}
void FetchKeys(KeyPair *pKeys)
{
printf("%d, %s\n",pKeys[0].nNum, pKeys[0].str);
}
I don't understand the difficulty. correct me if i'm wrong. To keep it simple, i avoided using vectors, templates and etc.
edit: to know size of struct, you can pass one more arg.