Friday, August 24, 2018

Foreach for double linked list without macro?

I am using double linked list and want to optimize it usage. I have a lot of places where I iterate throw all list elements. I want to use following defines:

//
// Iterates through all protected files
//
#define FOR_EACH_PROTECTED_FILE_START(protectedFile) \
    for(PLIST_ENTRY protectedFileEntry = filterData.ProtectedFilesHead.Flink; protectedFileEntry != &filterData.ProtectedFilesHead; protectedFileEntry = protectedFileEntry->Flink) { \
    protectedFile = CONTAINING_RECORD(protectedFileEntry, MY_PROTECTED_FILE_TYPE, EntryLink);


#define FOR_EACH_PROTECTED_FILE_END }

Is there way to do this without macro (macro is evil bla..bla.bla) to not put this constructs every place I want to iterate foreach file?

How do you like this style?

Solved

You could move the boilerplate logic into a function, which controls the loop and return a state.

inline int iterate_protected_files(ProtectedFile_t* current, /*other state data*/)
{
  /* Bolierplate stuff to get next file*/
  *current = whatever;
  return current_exists;
}

...

while (iterate_protected_files(&protectedFile))
{
  /* do stuff with a protected file */
}

You can stick to macro, but avoiding the braces in the macro itself:

#define FOR_EACH_PROTECTED_FILE(protectedFile) \
    for( \
        PLIST_ENTRY protectedFileEntry = filterData.ProtectedFilesHead.Flink, \
        protectedFile = CONTAINING_RECORD(protectedFileEntry, MY_PROTECTED_FILE_TYPE, EntryLink); \
        protectedFileEntry != &filterData.ProtectedFilesHead; \
        protectedFileEntry = protectedFileEntry->Flink, \
        protectedFile = CONTAINING_RECORD(protectedFileEntry, MY_PROTECTED_FILE_TYPE, EntryLink) \
    )

Use it like a for (as it actually is):

...
FOR_EACH_PROTECTED_FILE(protectedFile) {
    
}

No comments:

Post a Comment