Russian Qt Forum
Ноябрь 22, 2024, 13:54 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 [2]   Вниз
  Печать  
Автор Тема: Base64 в long double  (Прочитано 11495 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #15 : Ноябрь 28, 2012, 16:13 »

Мне тип данных неизвестен, поэтому я не знаю к чему делать cast. Методом тыка пробовал к int double - не выходит. Так что скорее всего это утопия. Надо смотреть как происходит сериализация. А этой возможности нет. Знаю точно, что это массив Дельфёвый структур. В структуре - 2 переменные типа Extended. Я их читаю, всё замечательно. А записать назад - не могу, не хватает этих преславутых 4 байтов.
Забудьте Вы эти академические термины long/int double. На практике есть double (8 байт) и float (4 байтв), остальное - дань истории "сопроцессоров". Делаете так

Код
C++ (Qt)
#pragma pack (push, 4)
struct CTest {
char rebyat1[10]; // первый урод (10 байт)
char rebyat2[10]; // второй
union {
  int rebyatenok_I;
  float rebyatenok_F;
};
};
#pragma pack (pop)
 
CTest test;
ba.read(&test, sizeof(test));
printf("int = %d, float = %f\n", test.rebyatenok_I, test.rebyatenok_F);
 
И смотрите какое значение разумное int или float

[/offtop]
"пресловутый" - от слова "слово", а не "слава"  Улыбающийся
« Последнее редактирование: Ноябрь 28, 2012, 16:15 от Igors » Записан
bsf
Гость
« Ответ #16 : Ноябрь 28, 2012, 20:38 »

Я извиняюсь, но QByteArray  нет метода read()
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #17 : Ноябрь 28, 2012, 21:04 »

Я извиняюсь, но QByteArray  нет метода read()
Ну не все же дается под copy/paste  Улыбающийся Из Ваших слов следует что есть блок данных 24 байта - ну и считайте его в эту структуру доступными средствами. Откуда-то де Вы данные берете
Записан
xokc
Птица говорун
*****
Offline Offline

Сообщений: 976



Просмотр профиля
« Ответ #18 : Ноябрь 28, 2012, 21:32 »

Мне тип данных неизвестен, поэтому я не знаю к чему делать cast. Методом тыка пробовал к int double - не выходит. Так что скорее всего это утопия. Надо смотреть как происходит сериализация. А этой возможности нет. Знаю точно, что это массив Дельфёвый структур. В структуре - 2 переменные типа Extended. Я их читаю, всё замечательно. А записать назад - не могу, не хватает этих преславутых 4 байтов.
Я правильно понимаю, что нужно реализовать какой-то обмен данными с Дельфи приложением и теперь читать из дельфового буфера получается, а обратно записывать - нет? Если - да, то для начала я бы оставил ровно те значения, которые которые там в этих 4 байтах и лежат. Если не прокатит - пробовать методом тыка - накапливать статистику и пытаться угадать, что именно там лежит. Дело в том, что того, что называется "массивом" в Delphi есть великое множество - начиная с банального array of и заканчивая TDynArray и т.п. Что именно применяется в данном конкретном случае и как оно сериализовалось - это вообще неочевидно. Кроме того, поскольку речь идёт массиве структур - то, с учётом неизвестного выравнивания этих структур, вообще можно мозг сломать.
P.S. Последние 4 байта из исходной последовательности дают 0x00442A83 или 4467331. Ничего разумного я в этом значении не нахожу - информации мало.
Записан
bsf
Гость
« Ответ #19 : Ноябрь 28, 2012, 21:35 »

Есть программа, писанная на Дельфях, я думаю вы все её знаете - SASPlanet. Она сохраняет метки в формате XML. В одном из параметров координата(ы) меток сериализуется в Base64. Благодаря добрым людям я научился читать координаты, а вот писать не получается эти координаты не получается. Полагаю, что эти 4 байта - это что то такое, что без них программа отказывается эту метку поднимать...
Вот что сделано, пусть и через *опу. Файл main.cpp

Код
C++ (Qt)
#include <QtGui/QApplication>
 
#include <QtCore/QTextCodec>
#include <QtCore/QDebug>
 
 
#if __BYTE_ORDER == __LITTLE_ENDIAN
 
#define MAN1OFFSET  0
#define MAN2OFFSET  4
#define EXP_OFFSET  6
#define lecpy       memcpy
 
#elif __BYTE_ORDER == __BIG_ENDIAN
 
#define MAN1OFFSET  4
#define MAN2OFFSET  0
#define EXP_OFFSET  0
 
static inline void *lecpy(char *dst, const char *src, size_t size) {
       dst += size;
       while (size--)
               *--dst = *src++;
       return dst;
}
 
#endif /* __BYTE_ORDER */
 
 
void fp80le_to_fp64(void *f64, const void *f80) {
       uint32_t man1, man2;
       uint16_t exp;
 
       lecpy((char *) &man1, (const char *) f80, 4);
       lecpy((char *) &man2, (const char *) f80 + 4, 4);
       lecpy((char *) &exp, (const char *) f80 + 8, 2);
 
       man1 >>= 11;
       man1 |= (man2 & 0x7ff) << 21;
       man2 >>= 11;
       man2 &= 0x000fffff;
       man2 |= (uint32_t) (exp & 0x8000) << 16;
       exp &= 0x7fff;
       exp = (uint16_t)(exp - 0x3c00);
       man2 |= (uint32_t) (exp & 0x7ff) << 20;
 
       memcpy((char *) f64 + MAN1OFFSET, &man1, 4);
       memcpy((char *) f64 + MAN2OFFSET, &man2, 4);
}
 
void fp64_to_fp80le(void *f80, const void *f64) {
       uint32_t man1, man2;
       uint16_t exp;
 
       memcpy(&man1, (const char *) f64 + MAN1OFFSET, 4);
       memcpy(&man2, (const char *) f64 + MAN2OFFSET, 4);
       memcpy(&exp,  (const char *) f64 + EXP_OFFSET, 2);
 
       man2 = ((man2 << 11) & 0x7ffff800)
            | ((man1 >> 21) & 0x000007ff);
       if (man1 || man2)
               man2 |= 0x80000000;
 
       man1 <<= 11;
       if (man1 & 0x800)
               man1 |= 0x7ff;
 
       exp = (uint16_t)(((((exp >> 4) & 0x7ff) + 0x3c00) & 0x7fff) | (exp & 0x8000));
 
       lecpy((char *) f80, (const char *) &man1, 4);
       lecpy((char *) f80 + 4, (const char *) &man2, 4);
       lecpy((char *) f80 + 8, (const char *) &exp, 2);
}
 
 
int main(int argc, char *argv[])
{
   QApplication a(argc, argv);
   QTextCodec::setCodecForTr(QTextCodec::codecForName("CP1251"));
 
   QByteArray decodeString = QByteArray::fromBase64("uB6F61G4npAEQASSsG8nERHeBECDKkQA");
 
   QByteArray ba = decodeString.mid(0,10);
   QByteArray bb = decodeString.mid(10,10);
   QByteArray bc = decodeString.mid(20,4);
 
   double *ld;
   double *lw;
 
   fp80le_to_fp64(ld, ba.data());
   fp80le_to_fp64(lw, bb.data());
 
   qDebug() << "size=" << decodeString.count();
   qDebug() << "1 - double=" << *ld;
   qDebug() << "2 - double=" << *lw;
   qDebug() << "3 - unknown=" << bc.data();
 
   char a1[10];
   char a2[10];
   fp64_to_fp80le(a1, ld);
   fp64_to_fp80le(a2, lw);
 
 
   QByteArray arr;
   arr.append(a1);
   arr.append(a2);
   arr.append(bc.data());
   arr = arr.toBase64();
 
   qDebug() << arr.data();
 
   return 0;
}
Результат естественно иной, во-первых, что то теряется при переводе типов, во-вторых, эти 4 байта, что в них? Загадка... Явный cast ни к чему не привёл...
Записан
V1KT0P
Гость
« Ответ #20 : Ноябрь 28, 2012, 22:43 »

Результат естественно иной, во-первых, что то теряется при переводе типов, во-вторых, эти 4 байта, что в них? Загадка... Явный cast ни к чему не привёл...
По идеи если есть три числа являющиеся координатами, и первые два это широта и долгота. То по идеи третье должно быть высота( скорее всего в метрах но может и в сантиметрах ).
А для того чтоб не терялось советую использовать long double.

добавлено:
Вот быстренько набросал две функции конвертации:
Код
C++ (Qt)
#include <QtCore/QDebug>
 
bool getPositionFromBase64( const QString &string, long double &longitude, long double &latitude, int &altitude )
{
   QByteArray data = QByteArray::fromBase64( string.toAscii() );
 
   if( data.size() != 24 ) {
       return false;
   }
 
   longitude = 0;
   latitude = 0;
 
   memcpy( &longitude, data.data(), 10 );
   memcpy( &latitude, data.data() + 10, 10 );
   memcpy( &altitude, data.data() + 20, 4 );
 
   return true;
}
 
QString getBase64FromPosition( const long double &longitude, const long double &latitude, const int &altitude )
{
   char data[24] = { 0 };
 
   memcpy( data, &longitude, 10 );
   memcpy( data + 10, &latitude, 10 );
   memcpy( data + 20, &altitude, 4 );
 
   return QString::fromAscii( QByteArray( data, 24 ).toBase64() );
}
 
int main(int argc, char *argv[])
{
   long double longitude;
   long double latitude;
   int altitude;
 
   if( getPositionFromBase64( "uB6F61G4npAEQASSsG8nERHeBECDKkQA", longitude, latitude, altitude ) ) {
       qDebug() << "Longitude:" << (double)longitude;
       qDebug() << "Latitude:" << (double)latitude;
       qDebug() << "Altitude:" << altitude;
       qDebug() << "Generate Base64:" << getBase64FromPosition( longitude, latitude, altitude );
   } else {
       qDebug() << "Wrong string";
   }
 
   return 0;
}
 
Вот вывод:
Цитировать
Longitude: 36.155
Latitude: 55.5167
Altitude: 4467331
Generate Base64: "uB6F61G4npAEQASSsG8nERHeBECDKkQA"
Как видно если правильно использовать С++ то получается компактно, правильно и красиво. А не та каша кода что у тебя =).
« Последнее редактирование: Ноябрь 28, 2012, 23:26 от V1KT0P » Записан
bsf
Гость
« Ответ #21 : Ноябрь 29, 2012, 09:11 »

Спасибо, буду пробовать! Много нового для себя открыл! Я новичок в этой области и учусь! А что касается высоты - то странная она какая - то! Да и СасПланета вряд-ли ее умеет определять. Это что то иное. Буду пробовать...
Записан
xokc
Птица говорун
*****
Offline Offline

Сообщений: 976



Просмотр профиля
« Ответ #22 : Ноябрь 29, 2012, 10:58 »

По идеи если есть три числа являющиеся координатами, и первые два это широта и долгота. То по идеи третье должно быть высота( скорее всего в метрах но может и в сантиметрах ).
Как-то лихо Вы привязки делаете. Если так уж пальцем в небо тыкать, то я бы не int рассматривал, а float в качестве высоты. Вообще, автор СасПланета вроде адекватен вполне. Может прямо у него и спросить?
Записан
bsf
Гость
« Ответ #23 : Ноябрь 29, 2012, 11:18 »

Как-то лихо Вы привязки делаете. Если так уж пальцем в небо тыкать, то я бы не int рассматривал, а float в качестве высоты. Вообще, автор СасПланета вроде адекватен вполне. Может прямо у него и спросить?
Спрашивали люди неоднократно, а получены уклончивые ответы, с типом Extended, ну и на том спасибо!
Записан
bsf
Гость
« Ответ #24 : Ноябрь 29, 2012, 12:59 »

Потестил, всё отлично экспортируется и импортируется SAS-ом. V1KT0P спасибо за помощь, то что нужно!
Записан
Страниц: 1 [2]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.13 секунд. Запросов: 23.