I'm losing my marble.

K

Kevin D. Quitt

Today is not a good day, concentration-wise. I'm trying to do something
that really ought to be simple, but I can't find a way.

I have a bunch of bit-map images, of various sizes, each in its own static
buffer. I want to have a static structure that lets me associate the name
with the buffers, so I can access the "files" by name.

I'm sure it's blindingly obvious, and that I'd see it were it not for the
flu. In the meantime, though, can I buy a clue?
 
J

Jeremy Yallop

Kevin said:
I have a bunch of bit-map images, of various sizes, each in its own static
buffer. I want to have a static structure that lets me associate the name
with the buffers, so I can access the "files" by name.

static struct {
const char *name;
const char *bitmap;
} bitmaps[] = {
{"first", first_buffer},
{"second", second_buffer},
};
 
A

Arthur J. O'Dwyer

Today is not a good day, concentration-wise. I'm trying to do something
that really ought to be simple, but I can't find a way.

I have a bunch of bit-map images, of various sizes, each in its own static
buffer. I want to have a static structure that lets me associate the name
with the buffers, so I can access the "files" by name.

Sounds like someone's been programming too much Perl again, or
Lisp, or something. :) Anyway, I *think* what you're wanting is
something along the lines of [UNTESTED CODE]:

struct Bitmap;

struct LookupEntry {
char *name;
struct Bitmap *file;
};

struct LookupTable {
int ntable;
struct LookupEntry table[100];
};

struct LookupEntry *add(struct LookupTable *tab, char *name,
struct Bitmap *file)
{
char *tmp;
if (tab->ntable >= 100) return NULL;
tmp = malloc(strlen(name)+1);
if (tmp == NULL) return NULL;
strcpy(tmp, name);
tab->table[tab->ntable].name = tmp;
tab->table[tab->ntable].file = file;
++tab->ntable;
return &tab->table[tab->ntable - 1];
}

struct LookupEntry *find(struct LookupTable *tab, char *name)
{
int i;
for (i=0; i < tab->ntable; ++i) {
char *tmp = tab->table[tab->ntable].name;
if (tmp == NULL) continue;
if (0 == strcmp(tmp, name))
return &tab->table;
}
return NULL;
}

int delete(struct LookupTable *tab, struct LookupEntry *entry)
{
int idx = (entry - tab->table);
free(entry->name);
--tab->ntable;
for (i=idx; i < tab->ntable; ++i) {
tab->table = tab->table[i+1];
}
return 0; /* successful deletion */
}


int main()
{
struct LookupTable mytab = {0};
struct LookupEntry *ent;
add(&mytab, "foo.bmp", NULL);
ent = find(&mytab, "bar.bmp");
if (ent)
delete(&mytab, ent);
return 0;
}


Replace the linear table by a binary tree or a hash table or something,
if you want better asymptotic performance. And check for bugs. ;-)

HTH,
-Arthur
 
K

Kevin D. Quitt

Sounds like someone's been programming too much Perl again, or
Lisp, or something. :)

Been too long for either of them. Thanks to both (quick) responders.

This is to be help screens for an embedded system. I want to define a
hierarchical set of structures that define each screen, including buttons
with multiple representations (being pressed, e.g.), and a function
associated with each button.

It wasn't the code for manipulating it, I just couldn't get everything
declared. Fortunately, that part of my stupidity has cleared. Here's
what I came up with in case anybody's interested.

-------8<-------

#ifndef _BUTTON_H_
#define _BUTTON_H_

typedef unsigned char uchar;

typedef enum
{ SC_EXIT, SC_Main, SC_Wireless, SC_DotQuad, SC_ESSID } SCREEN;

// Button defines size and which, of possibly 4, image to display

typedef struct
{
size_t cols, rows; // Pixels
int current; // If more than one set of images, which?
int active; // Use active rather than idle
uchar *idle[ 2 ]; // Primary & alternate idle view
uchar *actv[ 2 ]; // Primary & alternate active view
} Button;


// ButtonOp defines the operation of a given button: where it is on
// screen, its active touch values, the function to be called, and the
// images to use for it.

typedef struct _ButtonOp
{
int tp, lp; // Top left pixel
int tt, lt, bt, rt; // Top left, bottom right touch
SCREEN (*touchFunc)(struct _ButtonOp *, int, int, int);
Button *button;
} ButtonOp;


// MenuScreen defines the entire screen.

typedef struct
{
SCREEN theScreen;
int bcolor;
int tf, tb;
void (*initFunc)(void);
int buttons;
ButtonOp *button[ 20 ];
} MenuScreen;


extern MenuScreen MainScreen;


#endif
---->8----

And here's a stripped-down version of a screen definition:

----8<----
#include <stdio.h>
#include <stdlib.h>
#include "button.h"

static void sc1_initFunc( void );
static SCREEN sc1_bf1( ButtonOp *theBop, int ht, int vt, int up );
extern uchar sc1_b1i[], sc1_b1a[];

static Button sc1_b1 = { 100, 40, 0, 0, {sc1_b1i}, {sc1_b1a}};
static ButtonOp SC1_BB1 = { 20, 20, 1, 1, 2, 5, sc1_bf1, &sc1_b1 };

MenuScreen MainScreen =
{
SC_Main, 0, 0, 0, sc1_initFunc, 1, { &SC1_BB1 }
};

static void sc1_initFunc( void )
{
return;
}

static SCREEN sc1_bf1( ButtonOp *theBop, int ht, int vt, int up )
{
(void)theBop;(void)ht;(void)vt;(void)up;
return SC_DotQuad;
}


// In the real world, these are not strings, but raw bitmaps.
static uchar sc1_b1i[] = "sc1_b1i";
static uchar sc1_b1a[] = "sc1_b1a";

---->8----
 
G

Grumble

Irrwahn said:
It is.
Better: BUTTON_H
Even better (IMHO): H_BUTTON
My personal favorite: H_BUTTON_INCLUDED

Why do you think H_BUTTON is better than BUTTON_H?
 
S

Simon Biber

Grumble said:
Why do you think H_BUTTON is better than BUTTON_H?

H_FILENAME is better than FILENAME_H in case your header
file name starts with
E
PRI
SCN
LC_
SIG
or SIG_
because those identifiers (among others) are reserved in
certain contexts.
 
I

Irrwahn Grausewitz

Simon Biber said:
H_FILENAME is better than FILENAME_H in case your header
file name starts with
E
PRI
SCN
LC_
SIG
or SIG_
because those identifiers (among others) are reserved in
certain contexts.

Correct, and I like to have a consistent naming scheme,
therefore I always use H_<name>_INCLUDED.

Regards
 
C

CBFalconer

Grumble said:
Why do you think H_BUTTON is better than BUTTON_H?

Because if you follow the same id creation process, what are you
going to do with error.h? Or e<anything>.h.
 
D

Dan Pop

In said:
Because if you follow the same id creation process, what are you
going to do with error.h? Or e<anything>.h.

Frankly, I would use ERROR_H and E<ANYTHING>_H and assume the risks.
I value simple conventions that improve code readability more than
anal conformance to the C standard. YMMV.

Dan
 
K

Kevin D. Quitt

If that's the only objection, then I've truly surpassed myself. I may
switch to the H_ form, then but I'd be perfect. 8o)
 
B

Ben Pfaff

Kevin Goodsell said:
I'm not sure how many characters are required
to be significant in pre-processor symbols.

From 5.2.4.1 in C99:

- 63 significant initial characters in an internal
identifier or a macro name (each universal character
name or extended source character is considered a single
character)
 
K

Kevin Goodsell

Dan said:
Frankly, I would use ERROR_H and E<ANYTHING>_H and assume the risks.
I value simple conventions that improve code readability more than
anal conformance to the C standard. YMMV.

The convention I use is this:

#ifndef INCLUDED_SOMEFILE_H
#define INCLUDED_SOMEFILE_H 1

I think this is good for readability, and even a bit more logical than
the other conventions. It means I can do something like this:

#if INCLUDED_SOMEFILE_H

/* ... */

#endif

Which I think reads a little better than the alternative that most
conventions give. I've never actually had a reason to use this yet, though.

The number of characters in the identifier could be an issue, though. 9
non-unique characters at the start of the identifier might be asking for
trouble. I'm not sure how many characters are required to be significant
in pre-processor symbols.

-Kevin
 
S

Simon Biber

Ben Pfaff said:
From 5.2.4.1 in C99:

- 63 significant initial characters in an internal
identifier or a macro name (each universal character
name or extended source character is considered a single
character)

If you don't have a C99 compiler, note that in C89 2.2.4.1 the limit
is lower:
* 31 significant initial characters in an internal identifier or
a macro name
 
P

pete

Dan said:
Frankly, I would use ERROR_H and E<ANYTHING>_H and assume the risks.
I value simple conventions that improve code readability more than
anal conformance to the C standard. YMMV.

The standard reserves leading underscore
followed by an upper case letter identifiers, such as _BUTTON_H_.
That's a simple convention; newbies think it's easy to read
and they frequently assume that it's the correct form
for writing header guards.
I never heard of anybody getting bit by it.

But you're not saying that you would use _BUTTON_H_,
are you?
 
C

Christopher Benson-Manica

Kevin Goodsell said:
#ifndef INCLUDED_SOMEFILE_H
#define INCLUDED_SOMEFILE_H 1
^

Isn't the 1 unnecessary? Do you feel it improves readability?
 
B

Ben Pfaff

Christopher Benson-Manica said:
Isn't the 1 unnecessary? Do you feel it improves readability?

I prefer to include a value on my `#define's, so that I can then
use them in later conditionals without needing to write `defined
(...)' around them; e.g.
#if a || b || c || (d && e)
instead of
#if defined (a) || defined (b) || defined (c) || (defined (d) && defined (e))
However, I don't think I've ever wanted to test a set of include
guards that way.
 
K

Kevin Goodsell

Christopher said:
^

Isn't the 1 unnecessary? Do you feel it improves readability?

I began adding the 1 solely because it seemed more logical. If
"INCLUDED_SOMEFILE_H" is taken as a question, the answer should be
affirmative. Take the example I mentioned:

#if INCLUDED_SOMEFILE_H
/* ... */
#endif

This seems very natural to me. It reads as "If I've #included somefile.h..."

-Kevin
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top