While(1)
{
WCHAR wcImageName[80];
if ( pxmlNameTag->GetData(wcImageName, wcslen(wcImageName)) )
{
if ( !wcscmp(wcImageName, String2) )
{
Printf("String matched");
break;
}
else
{
Printf("In else");
}
}
else
{
Printf("Failed to get the data");
}
}
}
I am iterating the loop till i got the matching string. GetData is used to get the string into wcImageName. 1st time a am able to get the data into wcImageName and it is compared with string2. If not matched loop iterate 2nd time. i am declaring wcImageName again but GetData is not able to copy the data into wcImageName. because it is initialized. i have tried to initialize it with L'\0' but the same result.
Related
I have an std::set that contains unique values. I have an std::queue that holds the same values
in order to age the values in std::set.
I'd like to use a timer to determine when to pop a value from the queue and then erase the value from the set.
The timer is created/started every time data is added to an empty set/queue.
If data is added to a non-empty set/queue, no change is made to the timer.
The timer would fire every X milliseconds to execute a function.
The function would pop a value from the queue then erase that value from the set.
If the set/queue is now empty the timer would stop.
If the set/queue is not empty, no change is made to the timer.
This program runs in Windows 10.
Does this way make sense? Is there a better/more efficient/simpler way to age the data?
I've read the docs on Using Timer Queues so I see how the queue and the timers are created and destroyed. What I don't see is a recommendation for starting/stopping timers.
Should I be creating a new TimerQueueTimer to wait for X milliseconds once, run the func and then create a new TimerQueueTimer if the set/queue is not empty?
Should I instead create a single TimerQueueTimer to run periodically X milliseconds but delete it once the set/queue is empty?
Is there a 3rd technique I should use instead?
Here's my example code.
using unsignedIntSet = std::set<std::uint32_t>;
using unsignedIntQ = std::queue<std::uint32_t>;
unsignedIntQ agingQ;
unsignedIntSet agingSet;
HANDLE gDoneEvent = NULL;
HANDLE hTimer = NULL;
HANDLE hTimerQueue = NULL;
VOID CALLBACK ageTimer(PVOID lpParam, BOOLEAN TimerOrWaitFired)
{
if (!agingQ.empty())
{
auto c = agingQ.front();
agingSet.erase(c);
agingQ.pop();
if (!agingQ.empty())
{
// rerun CreateTimerQueueTimer() here?
}
}
SetEvent(gDoneEvent);
}
int createTimerForAgingQ()
{
// create timer if it doesn't already exist
if (gDoneEvent == NULL)
{
gDoneEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (gDoneEvent == NULL)
{
std::cerr << "CreateEvent() error: " << WSAGetLastError() << std::endl;
return -1;
}
hTimerQueue = CreateTimerQueue();
if (hTimerQueue == NULL)
{
std::cerr << "CreateTimerQueue() error: " << WSAGetLastError() << std::endl;
return -1;
}
if (!CreateTimerQueueTimer(&hTimer, hTimerQueue, (WAITORTIMERCALLBACK)ageTimer, NULL, 500, 0, WT_EXECUTEONLYONCE))
{
std::cerr << "CreateTimerQueueTimer() error: " << WSAGetLastError() << std::endl;
return -1;
}
}
}
void addUnique(unsigned char* buffer, int bufferLen)
{
// hash value
auto h = hash(buffer, bufferLen);
// test insert into set
auto setResult = agingSet.emplace(h);
if (setResult.second)
{
// enqueue into historyQ
agingQ.emplace(h);
if (!gDoneEvent) createTimerForAgingQ();
}
}
Research shows that the CreateTimerQueue/CreateTimerQueueTimer may not be the way to go.
Use of ThreadpoolTimer
So here is the scenario I am attempting to figure out how to implement using rxjs:
Load some set of metadata from a file/database/etc. Each element in the metadata has an id and additional information - like the location of the actual data. Currently, I am loading all of this metadata at the start of the application, asynchronously. After this data is loaded the Observable calls complete. Eventually I may add a refresh capability
At some later point in the application, I will need to load specific sets of data based upon what is available in the metadata. I am currently attempting to do this with a function like fetchData(ids:string[]):Observable. This is where I am unclear about how to proceed under the rxjs paradigm. I am equally unsure of what to do with requesting a single item using a function like fetchDatum(id:string):Observable
I can of course use filter to operate only on those IMetdata items emitted from the IMetadata Observable that match one of the names in the list - but I also need to confirm that ALL requested items are found in the IMetadata Observable emissions, and if not I need to error.
So if someone requests the IMetadata with id = "Bob" - but there is no such IMetadata emitted from the source Observable, then it needs to error. Or if they request { "Shirley", "Rex", "Samantha" } and there is no data for "Rex" then it should error.
I've considered using a Rx.Subject here, but from what I've read that is generally undesirable under the rxjs paradigm. Please advise on what approaches would work for this scenario under the rxjs paradigm. Thanks!
Here's the solution I came up with. This function creates an Observable that relies upon a IBufferEvaluator to tell it what to do with each item that is emitted by the source Observable. It can APPEND the item to the buffer, SKIP the emitted item, CLEAR the buffer, FLUSH the buffer to the subscriber, etc. Let me know if you find a better way to do this, especially if its an out-of-the-box rxjs solution. Thanks.
import Rx from 'rxjs/Rx';
export enum BufferAction {
APPEND, /** Append the current emission to the buffer and continue **/
SKIP, /** Do nothing, ignoring the current emission if applicable **/
FLUSH, /** This will ignore the current emission, if applicable, and flush the existing buffer contents */
CLEAR, /** Clear the buffer contents. Ignore the current emission, if applicable */
COMPLETE, /** Mark the Observable as Complete. The buffer will be cleared upon completion. **/
APPEND_THEN_FLUSH, /** Append the current emission to the buffer prior to flushing it **/
APPEND_THEN_COMPLETE, /** Append the current emission to the buffer and then complete **/
CLEAR_THEN_APPEND, /** Clear the buffer contents and then append the current emission to it */
FLUSH_THEN_APPEND, /** Flush the buffer contents and then append the current emission to it */
FLUSH_THEN_COMPLETE, /** Flush the buffer contents and then mark the Observable as complete */
APPEND_FLUSH_COMPLETE /** Append the current emission, flush the buffer, and then complete */
}
export function bufferActionToString(action: BufferAction):string
{
switch(action)
{
case BufferAction.APPEND: return "APPEND";
case BufferAction.SKIP: return "SKIP";
case BufferAction.FLUSH: return "FLUSH";
case BufferAction.CLEAR: return "CLEAR";
case BufferAction.COMPLETE: return "COMPLETE";
case BufferAction.APPEND_THEN_FLUSH: return "APPEND_THEN_FLUSH";
case BufferAction.APPEND_THEN_COMPLETE: return "APPEND_THEN_COMPLETE";
case BufferAction.CLEAR_THEN_APPEND: return "CLEAR_THEN_APPEND";
case BufferAction.FLUSH_THEN_APPEND: return "FLUSH_THEN_APPEND";
case BufferAction.FLUSH_THEN_COMPLETE: return "FLUSH_THEN_COMPLETE";
case BufferAction.APPEND_FLUSH_COMPLETE: return "APPEND_FLUSH_COMPLETE";
default: return "Unrecognized Buffer Action [" + action + "]";
}
}
export interface IBufferEvaluator<T>
{
evalOnNext(next:T, buffer: T[]):BufferAction;
evalOnComplete(buffer: T[]):BufferAction;
}
/** bufferWithEval.ts
* An Operator that buffers the emissions from the source Observable. As each emission is recieved,
* it and the buffered emissions are evaluated to determine what BufferAction to APPEND. You can APPEND
* the current emission value to the end of the buffered emissions, you can FLUSH the buffered emissions
* before or after appending the current emission value, you can SKIP the current emission value and then
* (optionally) FLUSH the buffer, and you can CLEAR the buffer before or after appending the current emission.
*
* The evalOnNext and evalOnComplete are expected to return a BufferAction to indicate
* which action to take. If no evalOnNext is supplied, it will default to APPENDing each emission. The evalOnComplete
* will default to FLUSH_THEN_COMPLETE. If evalOnNext or evalOnComplete throw an exception, the Observable will emit
* the exception and cease.
*/
export function bufferWithEval<T>
( source: Rx.Observable<T>,
evaluatorFactory?: () => IBufferEvaluator<T>
) : Rx.Observable<T[]>
{
/** if no evaluatorFactory supplied, use the default evaluatorFactory **/
if(!evaluatorFactory)
{
evaluatorFactory = () => {
return {
evalOnNext : function(next: T, buffer: T[]) { return BufferAction.APPEND; },
evalOnComplete : function(buffer: T[]) { return BufferAction.FLUSH; }
};
}
}
return new Rx.Observable<T[]>((subscriber: Rx.Subscriber<T[]>) =>
{
var _buffer = new Array<T>();
var _evaluator = evaluatorFactory();
var _subscription: Rx.Subscription = null;
function append(next: T)
{
_buffer.push(next);
}
function flush()
{
try
{
subscriber.next(_buffer);
}
finally
{
// Ignore any exceptions that come from subscriber.next()
clear();
}
}
function clear()
{
_buffer = new Array<T>();
}
function next(next: T)
{
try
{
var action = _evaluator.evalOnNext(next, _buffer.slice(0));
switch(action)
{
case BufferAction.APPEND: { append(next); break; }
case BufferAction.SKIP: { break; }
case BufferAction.FLUSH: { flush(); break; }
case BufferAction.CLEAR: { clear(); break; }
case BufferAction.COMPLETE: { complete(); break; }
case BufferAction.APPEND_THEN_FLUSH: { append(next); flush(); break; }
case BufferAction.APPEND_THEN_COMPLETE: { append(next); complete(); break; }
case BufferAction.APPEND_FLUSH_COMPLETE: { append(next); flush(); complete(); break; }
case BufferAction.CLEAR_THEN_APPEND: { clear(); append(next); break; }
case BufferAction.FLUSH_THEN_APPEND: { flush(); append(next); break; }
case BufferAction.FLUSH_THEN_COMPLETE: { flush(); complete(); break; }
default: throw new Error("next(): Invalid BufferAction '" + bufferActionToString(action) + "'");
}
}
catch(e)
{
error(e);
}
}
function complete()
{
try
{
var action = _evaluator.evalOnComplete(_buffer.slice(0));
switch(action)
{
case BufferAction.FLUSH_THEN_COMPLETE:
case BufferAction.FLUSH: { flush(); }
case BufferAction.CLEAR:
case BufferAction.COMPLETE: { break; }
case BufferAction.APPEND:
case BufferAction.APPEND_THEN_FLUSH:
case BufferAction.APPEND_THEN_COMPLETE:
case BufferAction.APPEND_FLUSH_COMPLETE:
case BufferAction.SKIP:
case BufferAction.CLEAR_THEN_APPEND:
case BufferAction.FLUSH_THEN_APPEND:
default: throw new Error("complete(): Invalid BufferAction '" + bufferActionToString(action) + "'");
}
clear();
subscriber.complete();
_subscription.unsubscribe();
}
catch(e)
{
error(e);
}
}
function error(err: any)
{
try
{
subscriber.error(err);
}
finally
{
_subscription.unsubscribe();
}
}
_subscription = source.subscribe(next, error, complete);
return _subscription;
});
}
I have an json object: [{a:"b"},{a:"c"},{a:"c"},{a:"d"},{a:"e"}]
which is stored in a Json::Value object.
I seem to be having some trouble with filtering that JSON object down to say: where only "a" = "c"
I was trying to do the following:
Json::Value data (*result.GetValue());
std::string filterValue = message->GetData()["Filter"];
std::string filterKey("a");
//above was just a quick variable definition for my example.
for ( auto row = data.begin(); row != data.end(); ++row )
{
if ( *row[filterKey].asString().compare(filterValue) != 0 )
{
//Remove this row from the JSON object.
}
}
Normally i am a Javascript dev, but i wanted to filter the results in C++11 before sending it to the client. In Javascript it is just as simple as: [].filter(function(ele){ if (ele["a"] == "c") return true; return false; }); but that is no help here.
In the Json::Value api, i didnt see any sort of filtering functions.
EDIT: The other issue is i was not sure how everything would act in the loop if i removed the item... something like: row->clear() or similar
just do:
Json::Value newOut;
for (Json::Value row : data )
{
if (row["a"].asString().compare("b") == 0)
{
newOut.append(row);
}
}
return newOut;
That will return the subset which matches. No need to do iterator in this case.
I am trying to stream audio data from disk using OpenAL's buffer queueing mechanism. I load and enqueue 4 buffers, start the source playing, and check in a regular intervals to refresh the queue. Everything looks like it's going splendidly, up until the first time I try to load data into a recycled buffer I got from alSourceUnqueueBuffers(). In this situation, alBufferData() always sets AL_INVALID_OPERATION, which according to the official v1.1 spec, it doesn't seem like it should be able to do.
I have searched extensively on Google and StackOverflow, and can't seem to find any reason why this would happen. The closest thing I found was someone with a possibly-related issue in an archived forum post, but details are few and responses are null. There was also this SO question with slightly different circumstances, but the only answer's suggestion does not help.
Possibly helpful: I know my context and device are configured correctly, because loading small wav files completely into a single buffer and playing them works fine. Through experimentation, I've also found that queueing 2 buffers, starting the source playing, and immediately loading and enqueueing the other two buffers throws no errors; it's only when I've unqueued a processed buffer that I run into trouble.
The relevant code:
static constexpr int MAX_BUFFER_COUNT = 4;
#define alCall(funcCall) {funcCall; SoundyOutport::CheckError(__FILE__, __LINE__, #funcCall) ? abort() : ((void)0); }
bool SoundyOutport::CheckError(const string &pFile, int pLine, const string &pfunc)
{
ALenum tErrCode = alGetError();
if(tErrCode != 0)
{
auto tMsg = alGetString(tErrCode);
Log::e(ro::TAG) << tMsg << " at " << pFile << "(" << pLine << "):\n"
<< "\tAL call " << pfunc << " failed." << end;
return true;
}
return false;
}
void SoundyOutport::EnqueueBuffer(const float* pData, int pFrames)
{
static int called = 0;
++called;
ALint tState;
alCall(alGetSourcei(mSourceId, AL_SOURCE_TYPE, &tState));
if(tState == AL_STATIC)
{
Stop();
// alCall(alSourcei(mSourceId, AL_BUFFER, NULL));
}
ALuint tBufId = AL_NONE;
int tQueuedBuffers = QueuedUpBuffers();
int tReady = ProcessedBuffers();
if(tQueuedBuffers < MAX_BUFFER_COUNT)
{
tBufId = mBufferIds[tQueuedBuffers];
}
else if(tReady > 0)
{
// the fifth time through, this code gets hit
alCall(alSourceUnqueueBuffers(mSourceId, 1, &tBufId));
// debug code: make sure these values go down by one
tQueuedBuffers = QueuedUpBuffers();
tReady = ProcessedBuffers();
}
else
{
return; // no update needed yet.
}
void* tConverted = convert(pData, pFrames);
// the fifth time through, we get AL_INVALID_OPERATION, and call abort()
alCall(alBufferData(tBufId, mFormat, tConverted, pFrames * mBitdepth/8, mSampleRate));
alCall(alSourceQueueBuffers(mSourceId, 1, &mBufferId));
if(mBitdepth == BITDEPTH_8)
{
delete (uint8_t*)tConverted;
}
else // if(mBitdepth == BITDEPTH_16)
{
delete (uint16_t*)tConverted;
}
}
void SoundyOutport::PlayBufferedStream()
{
if(!StreamingMode() || !QueuedUpBuffers())
{
Log::w(ro::TAG) << "Attempted to play an unbuffered stream" << end;
return;
}
alCall(alSourcei(mSourceId, AL_LOOPING, AL_FALSE)); // never loop streams
alCall(alSourcePlay(mSourceId));
}
int SoundyOutport::QueuedUpBuffers()
{
int tCount = 0;
alCall(alGetSourcei(mSourceId, AL_BUFFERS_QUEUED, &tCount));
return tCount;
}
int SoundyOutport::ProcessedBuffers()
{
int tCount = 0;
alCall(alGetSourcei(mSourceId, AL_BUFFERS_PROCESSED, &tCount));
return tCount;
}
void SoundyOutport::Stop()
{
if(Playing())
{
alCall(alSourceStop(mSourceId));
}
int tBuffers;
alCall(alGetSourcei(mSourceId, AL_BUFFERS_QUEUED, &tBuffers));
if(tBuffers)
{
ALuint tDummy[tBuffers];
alCall(alSourceUnqueueBuffers(mSourceId, tBuffers, tDummy));
}
alCall(alSourcei(mSourceId, AL_BUFFER, AL_NONE));
}
bool SoundyOutport::Playing()
{
ALint tPlaying;
alCall(alGetSourcei(mSourceId, AL_SOURCE_STATE, &tPlaying));
return tPlaying == AL_PLAYING;
}
bool SoundyOutport::StreamingMode()
{
ALint tState;
alCall(alGetSourcei(mSourceId, AL_SOURCE_TYPE, &tState));
return tState == AL_STREAMING;
}
bool SoundyOutport::StaticMode()
{
ALint tState;
alCall(alGetSourcei(mSourceId, AL_SOURCE_TYPE, &tState));
return tState == AL_STATIC;
}
And here's an annotated screen cap of what I see in my debugger when I hit the error:
I've tried a bunch of little tweaks and variations, and the result is always the same. I've wasted too many days trying to fix this. Please help :)
This error occurs when you trying to fill buffer with data, when the buffer is still queued to the source.
Also this code is wrong.
if(tQueuedBuffers < MAX_BUFFER_COUNT)
{
tBufId = mBufferIds[tQueuedBuffers];
}
else if(tReady > 0)
{
// the fifth time through, this code gets hit
alCall(alSourceUnqueueBuffers(mSourceId, 1, &tBufId));
// debug code: make sure these values go down by one
tQueuedBuffers = QueuedUpBuffers();
tReady = ProcessedBuffers();
}
else
{
return; // no update needed yet.
}
You can fill buffer with data only if it unqueued from source. But your first if block gets tBufId that queued to the source. Rewrite code like so
if(tReady > 0)
{
// the fifth time through, this code gets hit
alCall(alSourceUnqueueBuffers(mSourceId, 1, &tBufId));
// debug code: make sure these values go down by one
tQueuedBuffers = QueuedUpBuffers();
tReady = ProcessedBuffers();
}
else
{
return; // no update needed yet.
}
Alright so I remove an object from an array list, then break, but I still get OutOfBounds, I'm kinda confused, could someone help me, I've tried to isolate the problem, but I still can't figure it out.
Here is the error I get:
Exception in thread "Thread-2" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(ArrayList.java:635)
at java.util.ArrayList.get(ArrayList.java:411)
at GameFunctions.closestTarget(GameFunctions.java:37)
at GameFunctions.act(GameFunctions.java:147)
at GamePanel$1.run(GamePanel.java:50)
Here are the two methods causing me problems:
public void act(ArrayList<Germs> g, ArrayList<WhiteBloodCell> p, String actor)
{
if(actor.equals("Germs"))
{
for(int i=0;i<g.size();i++)
{
if(g.get(i) instanceof SPneumoniae)
{
g.get(i).move();
g.get(i).testBounds();
if(checkSize(g, i))
{
System.out.println("broken");
break;
}
}
}
}
else if(actor.equals("WhiteBloodCells"))
{
for(int i=0;i<p.size();i++)
{
p.get(i).setTarget(closestTarget(g, p.get(i)));
p.get(i).move();
}
}
}
And here is the method called that's removing the object:
public boolean checkSize(ArrayList<Germs> g, int i)
{
if(g.get(i).getRadius() > 30)
{
g.get(i).setRadius(30);
}
else if(g.get(i).getRadius() <= 0)
{
g.remove(i);
return true;
}
return false;
}
It looks like the error is due to there being nothing in the ArrayList of g.
Check out this area of your code:
else if(actor.equals("WhiteBloodCells"))
{
for(int i=0;i<p.size();i++)
{
p.get(i).setTarget(closestTarget(g, p.get(i)));
p.get(i).move();
}
}
See if that gives you any leads.
Edit -- The bug IS coming from the closestTarget function based on the exceptions listed.