How to read attributes in HDF5 file using C++ interface - hdf5

I have HDF5 file where the attributes are in below format
ATTRIBUTE "dtype" {
DATATYPE H5T_STRING {
STRSIZE 8;
STRPAD H5T_STR_NULLPAD;
CSET H5T_CSET_ASCII;
CTYPE H5T_C_S1;
}
DATASPACE SCALAR
DATA {
(0): "waveform"
}
}
I want to retrieve the waveform out of the attributes.I tried the below code snippet but it crashes
Group* signalgroup = new Group(outputgroup->openGroup(signalgrpName));
Attribute *attr = new Attribute(signalgroup->openAttribute("dtype"));
DataType *type = new DataType(attr->getDataType());
H5std_string test;
attr->read(*type, &test); //crashes here
Any inputs on how to read this?

This is very late, but I stumbled across this question searching something similar. The HDF5 API has an overloaded attribute.read() function that takes in a std::string by reference (not by pointer).
See here in the documentation: https://support.hdfgroup.org/HDF5/doc/cpplus_RM/class_h5_1_1_attribute.html#a8dae50d14de724c87507cba37f86793d (quoted below)
void H5::Attribute::read(const DataType& mem_type, H5std_string& strg) const
Parameters
mem_type - IN: Attribute datatype (in memory)
strg - IN: Buffer for read string

Related

How to cast String to TValue?

This code throws Invalid typecast at the last line prop->SetValue(control, value).
I assume I am casting "MyString" incorrectly. What's the right way to it?
for (int i = 0; i < MyForm->ControlCount; i++) {
TControl *control = MyForm->Controls[i];
if (control->Name == "MyTEdit") {
TRttiContext ctx;
TRttiType *type = ctx.GetType(control->ClassInfo());
TRttiProperty *prop = type->GetProperty(L"Text");
TValue value = TValue::From("MyString");
prop->SetValue(control, value);
}
}
It's supposed to loop through all the controls in MyForm until it finds the TEdit with the Name of MyTEdit, and change the text in the box to MyString.
My code is based on this answer. Unfortunately it did not provide an example of casting a String literal so a TValue so I am at a loss.
Update
After reading the answer to this question, I changed TValue value = TValue::From("MyString"); to this:
String myString = "MyString";
TValue value = TValue::From<UnicodeString>(myString);
Now I get the following error:
[ilink32 Error] Error: Unresolved external 'System::Rtti::TValue __fastcall System::Rtti::TValue::From<System::UnicodeString>(System::UnicodeString)' referenced from UNIT1.OBJ
I have included this at the top of Unit1.cpp:
#pragma explicit_rtti
#include <System.Rtti.hpp>
So I don't understand why it would say that.
Update 2
The problem disappeared when I switched to 64 bit from 32 bit.
TValue::From<T>() is a Delphi Generic method, and there are documented linker issues using Generics in C++:
How to Handle Delphi Generics in C++.
Try using the assignment operator= instead, as TValue has an assignment operator for UnicodeString:
String myString = "MyString";
TValue value;
value = myString;
TValue value;
value = String("MyString");

Converting the result from JSON GENERATE to EBCDIC

For one of my requirements I need the JSON GENERATE function in COBOL 6. My problem is, that it returns UTF-8, but I need the data in EBCDIC (CCSID 1140). Is there a way to convert this? Every solution I found uses national data types, but I have to use the NODBCS compiler option, so those don't work.
I do apologize for not first asking a question (but I am too new to StackOverflow to allow that.) The question would be "do you have C++ and can you link C++ with your COBOL?" I just tried this program:
#include <iconv.h>
class myConv
{
public:
static myConv globalConv;
size_t conv(char ** restrict f, unsigned int * restrict flen,
char ** restrict t, unsigned int * restrict tlen)
{
if (ok_)
{
return iconv(cd_, f, flen, t, tlen);
}
else
{
return (size_t)-1;
}
}
private:
myConv()
{
cd_ = iconv_open("1047", // EBCDID
"1208"); // UTF-8
ok_ = (cd_ != (iconv_t)-1);
// possibly indicate what the error is
}
~myConv()
{
if (ok_)
{
if (iconv_close(cd_) != 0)
{
// possibly indicate what the error is
}
}
}
bool ok_;
iconv_t cd_;
};
myConv myConv::globalConv;
extern "C" bool CNV(char * f, unsigned int flen,
char * t, unsigned int tlen)
{
return myConv::globalConv.conv(&f, &flen,
&t, &tlen) != (size_t)-1;
}
and the COBOL call looked like this:
json generate result from grp
call "CNV" using by reference result,
by value length of result,
by reference convertedres,
by value length of convertedres,
returning cres
and cres is a PIC S9(9) COMP data item which will have a non-zero value of the conversion succeeded.
Again, I apologize for not first asking if C++ is a possibility. (Or even C. The code could be easily done in C.) Also, the result is not quite perfect owing to the JSON GENERATE result being zero filled.

Converting NSStrings to C chars and calling a C function from Objective-C

I'm in an Objective-C method with various NSStrings that I want to pass to a C function. The C function requires a struct object be malloc'd so that it can be passed in - this struct contains char fields. So the struct is defined like this:
struct libannotate_baseManual {
char *la_bm_code; // The base code for this manual (pointer to malloc'd memory)
char *la_bm_effectiveRevisionId; // The currently effective revision ID (pointer to malloc'd memory or null if none effective)
char **la_bm_revisionId; // The null-terminated list of revision IDs in the library for this manual (pointer to malloc'd array of pointers to malloc'd memory)
};
This struct is then used in the following C function definition:
void libannotate_setManualLibrary(struct libannotate_baseManual **library) { ..
So that's the function I need to call from Objective-C.
So I have various NSStrings that I basically want to pass in there, to represent the chars - la_bm_code, la_bm_effectiveRevisionId, la_bm_revision. I could convert those to const chars by using [NSString UTF8String], but I need chars, not const chars.
Also I need to do suitable malloc's for these fields, though apparently I don't need to worry about freeing the memory afterwards. C is not my strong point, though I know Objective-C well.
strdup() is your friend here as that both malloc()s and strcpy()s for you in one simple step. It's memory is also released using free() and it does your const char * to char * conversion for you!
NSString *code = ..., *effectiveRevId = ..., *revId = ...;
struct libannotate_baseManual *abm = malloc(sizeof(struct libannotate_baseManual));
abm->la_bm_code = strdup([code UTF8String]);
abm->la_bm_effectiveRevisionId = strdup([effectiveRevId UTF8String]);
const unsigned numRevIds = 1;
abm->la_bm_effectiveRevisionId = malloc(sizeof(char *) * (numRevIds + 1));
abm->la_bm_effectiveRevisionId[0] = strdup([revId UTF8String]);
abm->la_bm_effectiveRevisionId[1] = NULL;
const unsigned numAbms = 1;
struct libannotate_baseManual **abms = malloc(sizeof(struct libannotate_baseManual *) * (numAbms + 1));
abms[0] = abm;
abms[1] = NULL;
libannotate_setManualLibrary(abms);
Good luck, you'll need it. It's one of the worst interfaces I've ever seen.

How to turn 4 bytes into a float in objective-c from NSData

Here is an example of turning 4 bytes into a 32bit integer in objective-c. The function readInt grabs 4 bytes from the read function and then converts it into a single 32 bit int. Does anyone know how I would convert 4 bytes to a float? I believe it is big endian. Basically I need a readFloat function. I can never grasp these bitwise operations.
EDIT:
I forgot to mention that the original data comes from Java's DataOutputStream class. The writeFloat function accordign to java doc is
Converts the float argument to an int using the floatToIntBits method
in class Float, and then writes that int value to the underlying
output stream as a 4-byte quantity, high byte first.
This is Objective c trying to extract the data written by java.
- (int32_t)read{
int8_t v;
[data getBytes:&v range:NSMakeRange(length,1)];
length++;
return ((int32_t)v & 0x0ff);
}
- (int32_t)readInt {
int32_t ch1 = [self read];
int32_t ch2 = [self read];
int32_t ch3 = [self read];
int32_t ch4 = [self read];
if ((ch1 | ch2 | ch3 | ch4) < 0){
#throw [NSException exceptionWithName:#"Exception" reason:#"EOFException" userInfo:nil];
}
return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
}
OSByteOrder.h contains functions for reading, writing, and converting integer data.
You can use OSSwapBigToHostInt32() to convert a big-endian integer to the native representation, then copy the bits into a float:
NSData* data = [NSData dataWithContentsOfFile:#"/tmp/java/test.dat"];
int32_t bytes;
[data getBytes:&bytes length:sizeof(bytes)];
bytes = OSSwapBigToHostInt32(bytes);
float number;
memcpy(&number, &bytes, sizeof(bytes));
NSLog(#"Float %f", number);
[data getBytes:&myFloat range:NSMakeRange(locationWhereFloatStarts, sizeof(float)] ought to do the trick.
Given that the data comes from DataOutputStream's writeFloat() method, then that is documented to use Float.floatToIntBits() to create the integer representation. intBitsToFloat() further documents how to interpret that representation.
I'm not sure if it's the same thing, but the xdr API seems like it might handle that representation. The credits on the man page refer to Sun Microsystems standards/specifications, so it seems likely it's related to Java.
So, it may work to do something like:
// At top of file:
#include <rpc/types.h>
#include <rpc/xdr.h>
// In some function or method:
XDR xdr;
xdrmem_create(&xdr, (char*)data.bytes + offset, data.length - offset, XDR_DECODE);
float f;
if (!xdr_float(&xdr, &f))
/* handle error */;
xdr_destroy(&xdr);
If the data consists of a whole stream in eXternal Data Representation, then you would create one XDR stream for the whole task of extracting items from it, and use many xdr_...() calls between creating and destroying it to extract all of the items.

how to read chinese from pdf in ios correctly

here is what I have done, but it appears disorderly. Thanks in advance.
1.use CGPDFStringCopyTextString to get the text from the pdf
2.encode the NSString to char*
NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
const char *char_content = [self.currentData cStringUsingEncoding:enc];
Below is how I get the currentData:
void arrayCallback(CGPDFScannerRef inScanner, void *userInfo)
{
BIDViewController *pp = (__bridge BIDViewController*)userInfo;
CGPDFArrayRef array;
bool success = CGPDFScannerPopArray(inScanner, &array);
for(size_t n = 0; n < CGPDFArrayGetCount(array); n += 1)
{
if(n >= CGPDFArrayGetCount(array))
continue;
CGPDFStringRef string;
success = CGPDFArrayGetString(array, n, &string);
if(success)
{
NSString *data = (__bridge NSString *)CGPDFStringCopyTextString(string);
[pp.currentData appendFormat:#"%#", data];
}
}
}
- (IBAction)press:(id)sender {
table = CGPDFOperatorTableCreate();
CGPDFOperatorTableSetCallback(table, "TJ", arrayCallback);
CGPDFOperatorTableSetCallback(table, "Tj", stringCallback);
self.currentData = [NSMutableString string];
CGPDFContentStreamRef contentStream = CGPDFContentStreamCreateWithPage(pagerf);
CGPDFScannerRef scanner = CGPDFScannerCreate(contentStream, table, (__bridge void *)(self));
bool ret = CGPDFScannerScan(scanner);
}
According to the Mac Developer Library
CGPDFStringCopyTextString returns a CFString object that represents a PDF string as a text string. The PDF string is given as a CGPDFString which is a series of bytes—unsigned integer values in the range 0 to 255; thus, this method already decodes the bytes according to some character encoding.
It is given none explicitly, so it assumes one encoding type, most likely the PDFDocEncoding or the UTF-16BE Unicode character encoding scheme which are the two encodings that may be used to represent text strings in a PDF document outside the document’s content streams, cf. section 7.9.2.2 Text String Type and Table D.1, Annex D in the PDF specification.
Now you have not told us from where you received your CGPDFString. I assume, though, that you received it from inside one of the document’s content streams. Text strings there, on the other hand, can be encoded with any imaginable encoding. The encoding used is given by the embedded data of the font the string is to be displayed with.
For more information on this you may want to read CGPDFScannerPopString returning strange result and have a look at PDFKitten.

Resources