Jump to content

Remy Lebeau

  • Content Count

  • Joined

  • Last visited

  • Days Won


Remy Lebeau last won the day on May 12

Remy Lebeau had the most liked content!

Community Reputation

133 Excellent


Technical Information

  • Delphi-Version
    Delphi XE2

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. Remy Lebeau

    JSON string value

    Um, yes it can. It has a full JSON library built-in.
  2. Remy Lebeau

    Undocumented "Interface flag" for IInvokable?

    Yes, sorry, that is what I meant.
  3. Remy Lebeau

    How to log raw data on Android?

    That is not what I was referring to. It takes multiple writes to the socket to send a web request, and multiple reads to receive a complete response. Those writes and reads get logged individually by Indy's Intercept components. They are not going to log a complete request in one go, or a complete response in one go. No, that is not the cause of the error. And besides, the TIdHTTP.Intercept gets assigned to the IOHandler.Intercept internally. So assigning the TIdHTTP.Intercept is just a shortcut. Make sure you DO NOT have multiple conflicting versions of Indy on your machine. If you do, then it is likely that the compiler is finding an old file that does not match the latest interface. That is perfectly fine, especially if you are only seeing it in the debugger. It just means the web server closed the connection on its end while TIdHTTP was still reading from the socket. Which is one possible way (not the preferred way, but still possible) for a web server to signal the end of a response. TIdHTTP should be handled such an error internally. You can configure your debugger to ignore that particular exception. Make sure you set the Active property of the TIdLog... component to True. Then those PHP devs don't really understand what they are doing. You can't post JSON using 'application/x-www.form-urlencoded'. If they are enforcing that, they are doing something wrong on their end. Makes sense, since you can't post JSON using 'application/x-www-form-urlencoded'.
  4. Remy Lebeau

    Undocumented "Interface flag" for IInvokable?

    OK. https://quality.embarcadero.com/browse/RSP-24631 I'm aware of that. But that is not the exact text you originally showed, which is why I questioned it.
  5. Remy Lebeau

    How to log raw data on Android?

    TIdLogEvent is not an abstract class, as it does implement all of the abstract methods of TIdLogBase. There is also TIdLogFile, which is not abstract, either. TIdInterceptSimLog and TIdLogFile are completely different file loggers. They write data in different formats. TIdLogFile is more "raw", logging data as-is, with optional timestamp and text replacements of CR and LF bytes. While TIdInterceptSimLog prefixes each read/write with a summary line describes whether the data is textual with a EOL present, or is raw bytes and what the byte size is, and appends a line break after each data.
  6. Remy Lebeau

    How to log raw data on Android?

    Why not TIdLogFile instead? Especially since you are saving data to files. For debugging purposes, you DON'T want individual reads/writes to be logged to separate files. It makes more sense to keep them in a single file. Even if you use TIdLogEvent with separate files for input and output, you are creating filenames based on timestamps with seconds precision, so you are likely to end up with multiple files that contain smaller pieces of the overall data. At the very least, I would suggest either dropping the seconds from the filename, or use the timestamp at the very beginning of the initial request rather than the timestamps of the individual reads/writes. Also FYI, TFile.WriteAllText() overwrites an existing file. You need TFile.AppendAllText() instead. Even if it were secured with HTTPS, the TIdLog... components would be able to log the unencrypted HTTP data, as they log outgoing data before it is encrypted, and log incoming data after it is decrypted. I see nothing in your code that would cause an Abstract error, as there are no abstract classes being used. That being said, you don't need to instantiate an IOHandler manually in this case, since you are not using HTTPS. TIdHTTP has its own Intercept property, and will create an IOHandler internally for you: var NewsRec: TGetNewsRequest; Json: string; SS: TStringStream; Http: TIdHTTP; LogEvent: TIdLogEvent; Response: string; ResponseRec: TGetNewsResponse; begin // some non-relevant code for json preperation, etc. deleted SS := TStringStream.Create(Json); try LogEvent := TIdLogEvent.Create(nil); try LogEvent.OnSent := frmMain.IdLogEvent1Sent; LogEvent.OnReceived := frmMain.IdLogEvent1Received; Http := TIdHTTP.Create(nil); try Http.Intercept := LogEvent; Http.Request.ContentType := 'application/x-www-form-urlencoded'; Response := Http.Post(GetNewsURL, SS); // try..except removed to simplify code finally Http.Free; end; finally LogEvent.Free; end; finally SS.Free; end; // some non-relevant code to deal with result deleted end; On a side note, 'application/x-www-form-urlencoded' is the wrong ContentType to use for JSON data, use 'application/json' instead. If you really want to send an 'application/x-www-form-urlencoded' post, you need to use the overloaded version of TIdHTTP.Post() that takes a TStrings as input, not a TStream.
  7. Remy Lebeau

    Undocumented "Interface flag" for IInvokable?

    Are you saying the returned IntfFlags *contains* a bit that *represents* an enum value of 3? Or that the IntfFlags *itself* is a numeric value of 3? In the former case, I have seen something similar before: https://stackoverflow.com/questions/49950534/strange-behaviour-of-typeinfo-by-anonymous-methods In the latter case, the TRttiInterfaceType.IntfFlags property returns a TIntfFlags Set, and a Set is implemented as a bitmask, where each bit represents a specific enum value. A bitmask value of 3 means the 1st 2 bits in the bitmask are set. And since TIntfFlags contains all of the TIntfFlag values, that would mean a bitmask value of 3 has the ifHasGuid and ifDispInterface flags enabled. Which, I guess the latter does not make sense in this situation, because IInvokable is not a dispinterface. So, it must be the former.
  8. Remy Lebeau

    Good design for "file was just saved" message

    When I display filenames in Task Dialogs, I like to put them in the ExpandedText section, so they are hidden initially but the user can choose to see them if desired.
  9. InitInstance() fills the allocated memory with zeros and inserts a pointer to the class's vtable at the front of the memory You should not need the type cast. ANY pointer can be assigned as-is to an untyped Pointer variable/parameter.
  10. Remy Lebeau

    Good design for "file was just saved" message

    What about using a single TButton with its Style set to bsSplitButton and a DropDownMenu assigned? The button could default to "Open", but the drop-down menu could have other actions for the user to choose from. Here is rough mockup of it (I don't have access to a working IDE at the moment):
  11. Remy Lebeau

    converting a C enum to Delphi

    In both C/C++ and Delphi, enums begin at 0, and values are sequential, unless explicitly otherwise stated. Since VmbPixelLayoutYCbYCr422 and VmbPixelLayoutYCbCr444 do not have explicit values, they are implicitly +1 from the values they immediately follow. Thus: VmbPixelLayoutYCbYCr422 = VmbPixelLayoutCbYYCrYY411 (= VmbPixelLayoutYUV411 = 8 ) + 1 = 9 VmbPixelLayoutYCbCr444 = VmbPixelLayoutCbYCrY422 (= VmbPixelLayoutYUV422 = 9 ) + 1 = 10
  12. Remy Lebeau

    converting a C enum to Delphi

    Embarcadero's documentation says otherwise: Enumerated Types with Explicitly Assigned Ordinality
  13. Remy Lebeau

    Login Form - 3 tries.

    Double check to make sure that you don't have a ModalResult assigned to btnOK itself. You should be able to click on btnOK and call DoLogin() as many times as you want without closing the Form until the Form's ModalResult is assigned when the Fail counter reaches the desired limit.
  14. In addition, in XE7+ the compiler has an (undocumented) GetTypeKind() intrinsic function: function GetTypeKind(T: TypeIdentifier): TTypeKind; So you can do this instead: procedure TCSVSchemaBuilder.BuldSchema<T>(SchemaTemplate: T); begin FSchemaItems.Clear; FNumRequired := 0; case GetTypeKind(T) of tkClass: BuildSchemaFromClass(...); tkRecord: BuildSchemaFromRecord(...); tkInterface: BuildSchemaFromInterface(...); else raise EImportSchema.Create('Cannot create schema by type'); end; if FSchemaItems.Count = 0 then raise EImportSchema.Create('Schema is missing critical information. Cannot proceed'); end; Prior to XE7, you can replace GetTypeKind() with this instead: case PTypeInfo(TypeInfo(T)).Kind of Either way, the advantage is that T's Kind is known at compile time, which allows this code to optimize out unused code branches at compile-time, whereas the original code does not allow that since the Kind is being queried dynamically at runtime.
  15. Remy Lebeau

    quality.embarcadero.com down?

    Works fine for me just now.