Prev: 443413 M3i Zero , Ezflash Dsi , R4i Dsi 43531
Next: Can I get the Mime Content Type from a byte array?
From: Peter Duniho on 19 Sep 2009 03:21 On Fri, 18 Sep 2009 22:27:43 -0700, Michelle <michelle(a)notvalid.nomail> wrote: > [...] > It works without error (so far we've verified) and that's most important. > But efficiency is the second most important. > I do not have enough knowledge and experience with C # to construct your > explanation into code. > If you have time and opportunity to spare, you might want to send an > example. I would at least grateful. Here's a short snippet illustrating what I mean. Assume a structure like this: struct PatternSubset { public readonly int ib; public readonly byte[] rgb; public PatternSubset(int ib, byte[] rgb) { this.ib = ib; this.rgb = rgb; } } then, rather than just calling FRangesEqual() for a given pattern, call it in a loop like this: // This is probably passed into the search method, but I'll just show a regular // local variable initialization here PatternSubset[] rgps = new { new PatternSubset(0, new byte[] { 0x07, 0x00 }), new PatternSubset(3, new byte[] { 0x00, 0x00, 0x00, 0x07, 0x00 }), new PatternSubset(9, new byte[] { 0x00, 0x00, 0x00, 0x08, 0x00 }) }; // Instead of a single call to FRangesEqual(), you'll have something like this: bool fMatches = true; foreach (PatternSubset ps in lps) { if (!FRangesEqual(rgbBlockCur, ibOffset + ps.ib, ps.rgb.Length, ps.rgb)) { fMatches = false; break; } } if (fMatches) { // do whatever } That's the basic idea. The above doesn't do anything to deal with the cross-block boundary, so you'll have to adapt the idea shown in the example to the code you're actually using. It won't work as it is shown exactly above. But if you take the time to understand both the original example, and the example above, you should be able to combine them correctly. One suggestion for doing that combination: you'll note that in the above, the call to FRangesEqual() is logically equivalent to the call to FRangesEqual() in the original example. So, the calculated value "ibOffset + ps.ib" is logically equivalent to the "ibOffset" value in the original example. It may make the code more readable if you abstract out the logic that handles dealing with one or two blocks, like this: In the original example, instead of the section of code that looks like this: if (ibOffset + rgbPattern.Length <= cbBlockCur) { if (FRangesEqual(rgbBlockCur, ibOffset, rgbPattern.Length, rgbPattern)) { return ibBaseOffset + ibOffset; } } else if (ibOffset + rgbPattern.Length <= cbBlockCur + cbBlockNext) { if (FRangesEqual(rgbBlockCur, ibOffset, cbBlockCur - ibOffset, rgbPattern) && FRangesEqual(rgbBlockNext, 0, ibOffset + rgbPattern.Length - cbBlockCur, rgbPattern)) { return ibBaseOffset + ibOffset; } } else { return -1; } You'd replace it with a section of code that looks like this: if (ibOffset + rgbPattern.Length <= cbBlockCur + cbBlockNext) { if (FRangesEqualInBlocks(rgbBlockCur, cbBlockCur, rgbBlockNext, ibOffset, rgbPattern)) { return ibBaseOffset + ibOffset; } } else { return -1; } The FRangesEqualInBlocks() method then looks like this (yes, I know that's a lot of method arguments...and that's not even allowing for the one more argument required if you want error checking): bool FRangesEqualInBlocks(byte[] rgbBlockCur, int cbBlockCur, byte[] rgbBlockNext, long ibOffset, byte[] rgbPattern) { if (ibOffset + rgbPattern.Length <= cbBlockCur) { return FRangesEqual(rgbBlockCur, ibOffset, rgbPattern.Length, rgbPattern); } return FRangesEqual(rgbBlockCur, ibOffset, cbBlockCur - ibOffset, rgbPattern) && FRangesEqual(rgbBlockNext, 0, ibOffset + rgbPattern.Length - cbBlockCur, rgbPattern); } Finally, applying that to the example I started out with in this post, instead of the code I wrote where you'd just call FRangesEqual(), instead you'd call this new FRangesEqualInBlocks() method: foreach (PatternSubset ps in lps) { if (!FRangesEqualInBlocks(rgbBlockCur, cbBlockCur, rgbBlockNext, ibOffset + ps.ib, ps.rgb)) { fMatches = false; break; } } Oh, one other thing. The original code example was able to detect the termination condition based solely on "ibOffset" as compared to the remaining data available. You can do basically the same thing even with the list of segments to compare; just apply that logic to the last segment in the list (you may want to validate the list of segments by ensuring that they are in order of the offset, and that they don't overlap...that is, the offset plus the length of the byte[] for one segment is less than the offset for the next segment). Validation might look something like this: int cbPattern = -1; foreach (PatternSubset ps in rgps) { if (ps.ib <= cbPattern) { // report error // note that technically, "ps.ib < cbPattern" would // be okay, but you may want to consider the "equals" // condition an error anyway, because if it happens, // it means someone passed in multiple pattern subsets // that could have been merged. It just depends on how // strict you want to be with callers. } cbPattern = ps.ib + ps.rgb.Length; } And then the termination condition becomes this: if (ibOffset + cbPattern <= cbBlockCur + cbBlockNext) { // code to loop through PatternSubset[] } else { return -1; } Hope that helps, and that walking you through the different variations leading to the eventual solution is okay. Hopefully that allows you to understand the evolution of the design better, without confusing you too much, and leaving some actual work for _you_ to do. :) Pete
From: Michelle on 20 Sep 2009 03:08 Peter, Thanks for the code and explanation. This week i'm going to work with the code and I'll let you know if it succeeded. Regards, Michelle
From: Michelle on 24 Sep 2009 02:37
Peter, I'm stuck. I have your code and explanations read several times teh last days, but I do not manage it. I give up. I'm lost with the different variants. It's confusing me to much. You've inserted so much time and ernergie already, that's all I can ask of you. Very sincere thanks for all the work and patience. Regards, Michelle. |