By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,148 Members | 779 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,148 IT Pros & Developers. It's quick & easy.

Ugly C looking code

P: n/a
I've been working on a project to map a MySQL database to a C++ class.
Well, I actually got it to work, but some if it I just feel is exceptionally
ugly. For example, in my operator<< override:

template<typename T>
CMySQLTable& operator<<(const T& ClassTable)
{
/**/
}

I have a switch statement and code that looks like this:

switch ( ThisField.FieldType() )
{
case SQL_FieldType_Unknown:
std::cerr << " SQL_FieldType_Unknown: Error!" << std::endl;
assert(false);
break;

case SQL_FieldType_VarChar:
ThisField = *reinterpret_cast<const std::string*>( reinterpret_cast<const
char*>( &ClassTable ) + ThisOffset.Offset );
break;

case SQL_FieldType_Int:
ThisField = *reinterpret_cast<const int*>( reinterpret_cast<const
char*>( &ClassTable ) + ThisOffset.Offset );
break;

case SQL_FieldType_UnsignedInt:
ThisField = *reinterpret_cast<const unsigned int*>(
reinterpret_cast<const char*>( &ClassTable ) + ThisOffset.Offset );
break;

case SQL_FieldType_Bool:
ThisField = *reinterpret_cast<const bool*>( reinterpret_cast<const
char*>( &ClassTable ) + ThisOffset.Offset );
break;

/**/
}

It's the complicated casts that I find ugly. And in the operator>override
it's just as bad, if not worst.

template<typename T>
CMySQLTable& operator>>(T& ClassTable)
{
/**/
}

switch ( ThisField.FieldType() )
{
case SQL_FieldType_Unknown:
std::cerr << " SQL_FieldType_Unknown: Error!" << std::endl;
assert( false );
break;

case SQL_FieldType_VarChar:
*reinterpret_cast<std::string*>( reinterpret_cast<char*>( &ClassTable ) +
ThisOffset.Offset ) = ThisField.Value();
break;

case SQL_FieldType_Int:
*reinterpret_cast<int*>( reinterpret_cast<char*>( &ClassTable ) +
ThisOffset.Offset ) = StrmConvert<int>( ThisField.Value() );
break;

case SQL_FieldType_UnsignedInt:
*reinterpret_cast<unsigned int*>( reinterpret_cast<char*>( &ClassTable )
+ ThisOffset.Offset ) = StrmConvert<unsigned int>( ThisField.Value() );
break;

case SQL_FieldType_Bool:
*reinterpret_cast<bool*>( reinterpret_cast<char*>( &ClassTable ) +
ThisOffset.Offset ) = ThisField.Value() == "0" ? false : true;
break;
/**/
}

Can you think of a cleaner way to do this, or is this the way I'm stuck with
just because of what I'm doing (working with pointers and offsets).

What I'm doing, and it works in test, is I have a class include a subclass
in which I map the variables I want to pull from the database.

void CCharFieldMap::SetMap( CCharacter* Base )
{
SetBase( Base );
SetOffset( "Version", Base->Version );
SetOffset( "Name", Base->Name );
SetOffset( "Password", Base->Password );
SetOffset( "Avatar", Base->Avatar );
SetOffset( "Race", *reinterpret_cast<unsigned int*>( &Base->Race ) );
SetOffset( "Sex", *reinterpret_cast<unsigned int*>( &Base->Sex ) );
SetOffset( "GM", Base->GM );
/**/
}

My overrides for << and >look at this instance that contains information
about the variables (Type of variable, offset into class) and transfer data
back and forth using the base address of the passed reference and the
offsets.

It's the only way I could find to do it, and right now it seems it will be
extremely easy to use for the user (me) for new classes. No longer do I
have to go through SQL schenanigans to pull data to/from databases, I can
simply do code like:

if ( ! PlayerTable.init( "192.168.1.100", "serpardum", "somepassword",
"abyssal", "players", 3307 ) )
{
std::cerr << "Initialization failed" << std::endl;
std::string wait;
std::getline( std::cin, wait );

return 1;
}

if ( ! PlayerTable.LoadTable( "Name", "Serpardum" ) )
{
std::cout << "Serpardum not found" << std::endl;
return 1;
}

PlayerTable >Player;

which would open my MySQL database, load the record where the Name ==
Serpardum, and load it into my class.

I like it, but as I said, I find some of it ugly. Any suggestions?
Aug 25 '06 #1
Share this Question
Share on Google+
5 Replies


P: n/a
Jim Langston wrote:
I've been working on a project to map a MySQL database to a C++ class.
Well, I actually got it to work, but some if it I just feel is exceptionally
ugly. For example, in my operator<< override:
Why don't you just save all the fields as strings and convert them as
required?
--
Ian Collins.
Aug 26 '06 #2

P: n/a
Ian Collins wrote:
Jim Langston wrote:
>I've been working on a project to map a MySQL database to a C++ class.
Well, I actually got it to work, but some if it I just feel is
exceptionally
ugly. For example, in my operator<< override:
Why don't you just save all the fields as strings and convert them as
required?
Why not store a table of pointers into the MySQL result itself, and fetch
them out on demand, typesafely?

--
Phlip
http://c2.com/cgi/wiki?ZeekLand <-- NOT a blog!!!
Aug 26 '06 #3

P: n/a

Ian Collins wrote:
Jim Langston wrote:
I've been working on a project to map a MySQL database to a C++ class.
Well, I actually got it to work, but some if it I just feel is exceptionally
ugly. For example, in my operator<< override:
Why don't you just save all the fields as strings and convert them as
required?
I don't quite understand what you mean. All the fields are strings in
the CField class. The operator>and operator<< overrides are doing
the conversion. So what did you mean beyond this?

Aug 26 '06 #4

P: n/a

Phlip wrote:
Ian Collins wrote:
Jim Langston wrote:
I've been working on a project to map a MySQL database to a C++ class.
Well, I actually got it to work, but some if it I just feel is
exceptionally
ugly. For example, in my operator<< override:
Why don't you just save all the fields as strings and convert them as
required?

Why not store a table of pointers into the MySQL result itself, and fetch
them out on demand, typesafely?
Please explain? Currently when I read the table it goes into a CField
map which contains the string that MySQL returns and the data type. So
in my CMySQLTable class I have a map of <std::string, CFieldwith the
std::string being the field name, and CField being the value (as a
string) and data type as stored in MySQL.

Oh, I think I see what you are saying, and I even thought about this.
Instead of storing them as std::string in the CField, store them as the
data type itself. I couldnt' figure out a good way to do this in a
map. A union wouldn't work as the data would be different sizes. And
even if I used a union of pointers (pointing to std::string, int,
unsigned int, etc...) I would still wind up having to use a switch
based on type.

Even if I came up with a way to store the data as it's type
transparently, the only thing this would save me is not having to run
StrmConvert</* type */>( ) on the strings. I don't see how it could
save me on the casting into the class they're being loaded into.

Aug 26 '06 #5

P: n/a
Se*******@gmail.com wrote:
Ian Collins wrote:
>>Jim Langston wrote:
>>>I've been working on a project to map a MySQL database to a C++ class.
Well, I actually got it to work, but some if it I just feel is exceptionally
ugly. For example, in my operator<< override:

Why don't you just save all the fields as strings and convert them as
required?


I don't quite understand what you mean. All the fields are strings in
the CField class. The operator>and operator<< overrides are doing
the conversion. So what did you mean beyond this?
I might have misunderstood your code, I though you were converting each
field value in a result as it was copied.

Looking at my own MySQL wrappers, I do pretty much what Phlip said and
store the query result and use the subscript operator to index rows and
again within the row to access fields. The field access converts the
value to std::string on read and from the base type on write.

--
Ian Collins.
Aug 26 '06 #6

This discussion thread is closed

Replies have been disabled for this discussion.