hrev44668 adds 2 changesets to branch 'master' old head: 7ba2bcac6f3d71246a2f8506c369babfd101ba3a new head: a8b45a34711cd202f085a2acb22b151cb2019271 ---------------------------------------------------------------------------- 225c8cc: Minor cleanup, no functional change. a8b45a3: Added a test to compare various header parsers. * HaikuMailFormatFilter is using the new extract_from_header() method to retrieve its fields, but that one is often rather slow in comparison. * Added a test parse_fields() method that outperforms it considerably. [ Axel DÃrfler <axeld@xxxxxxxxxxxxxxxx> ] ---------------------------------------------------------------------------- 4 files changed, 253 insertions(+), 35 deletions(-) .../kernel/drivers/audio/hda/hda_controller.cpp | 66 +++-- src/tests/kits/Jamfile | 1 + src/tests/kits/mail/Jamfile | 11 + src/tests/kits/mail/header_test.cpp | 210 ++++++++++++++++ ############################################################################ Commit: 225c8cc59aac7901a84ca8baf9957037b31e62fb URL: http://cgit.haiku-os.org/haiku/commit/?id=225c8cc Author: Axel DÃrfler <axeld@xxxxxxxxxxxxxxxx> Date: Mon Oct 1 07:11:35 2012 UTC Minor cleanup, no functional change. ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/drivers/audio/hda/hda_controller.cpp b/src/add-ons/kernel/drivers/audio/hda/hda_controller.cpp index 870a020..c101540 100644 --- a/src/add-ons/kernel/drivers/audio/hda/hda_controller.cpp +++ b/src/add-ons/kernel/drivers/audio/hda/hda_controller.cpp @@ -31,7 +31,7 @@ (((controller)->num_input_streams + (controller)->num_output_streams \ + (index)) * HDAC_STREAM_SIZE) -#define ALIGN(size, align) (((size) + align - 1) & ~(align - 1)) +#define ALIGN(size, align) (((size) + align - 1) & ~(align - 1)) #define PAGE_ALIGN(size) (((size) + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1)) static const struct { @@ -58,32 +58,33 @@ static pci_x86_module_info* sPCIx86Module; static inline void -update_pci_register(hda_controller* controller, uint8 reg, uint32 mask, uint32 value, uint8 size) +update_pci_register(hda_controller* controller, uint8 reg, uint32 mask, + uint32 value, uint8 size) { - uint32 tmp = (gPci->read_pci_config)(controller->pci_info.bus, + uint32 originalValue = (gPci->read_pci_config)(controller->pci_info.bus, controller->pci_info.device, controller->pci_info.function, reg, size); (gPci->write_pci_config)(controller->pci_info.bus, controller->pci_info.device, controller->pci_info.function, - reg, size, (tmp & mask) | value); + reg, size, (originalValue & mask) | value); } static inline rirb_t& -current_rirb(hda_controller *controller) +current_rirb(hda_controller* controller) { return controller->rirb[controller->rirb_read_pos]; } static inline uint32 -next_rirb(hda_controller *controller) +next_rirb(hda_controller* controller) { return (controller->rirb_read_pos + 1) % controller->rirb_length; } static inline uint32 -next_corb(hda_controller *controller) +next_corb(hda_controller* controller) { return (controller->corb_write_pos + 1) % controller->corb_length; } @@ -105,9 +106,9 @@ stream_handle_interrupt(hda_controller* controller, hda_stream* stream, stream->Write8(HDAC_STREAM_STATUS, status); - if (status & STATUS_FIFO_ERROR) + if ((status & STATUS_FIFO_ERROR) != 0) dprintf("hda: stream fifo error (id:%ld)\n", stream->id); - if (status & STATUS_DESCRIPTOR_ERROR) + if ((status & STATUS_DESCRIPTOR_ERROR) != 0) dprintf("hda: stream descriptor error (id:%ld)\n", stream->id); if ((status & STATUS_BUFFER_COMPLETED) == 0) { @@ -343,7 +344,8 @@ reset_controller(hda_controller* controller) // Enable unsolicited responses control = controller->Read32(HDAC_GLOBAL_CONTROL); - controller->Write32(HDAC_GLOBAL_CONTROL, control | GLOBAL_CONTROL_UNSOLICITED); + controller->Write32(HDAC_GLOBAL_CONTROL, + control | GLOBAL_CONTROL_UNSOLICITED); return B_OK; } @@ -359,13 +361,8 @@ reset_controller(hda_controller* controller) static status_t init_corb_rirb_pos(hda_controller* controller) { - uint32 memSize, rirbOffset, posOffset; - uint8 corbSize, rirbSize, posSize; - status_t rc = B_OK; - physical_entry pe; - // Determine and set size of CORB - corbSize = controller->Read8(HDAC_CORB_SIZE); + uint8 corbSize = controller->Read8(HDAC_CORB_SIZE); if ((corbSize & CORB_SIZE_CAP_256_ENTRIES) != 0) { controller->corb_length = 256; controller->Write8(HDAC_CORB_SIZE, CORB_SIZE_256_ENTRIES); @@ -378,7 +375,7 @@ init_corb_rirb_pos(hda_controller* controller) } // Determine and set size of RIRB - rirbSize = controller->Read8(HDAC_RIRB_SIZE); + uint8 rirbSize = controller->Read8(HDAC_RIRB_SIZE); if (rirbSize & RIRB_SIZE_CAP_256_ENTRIES) { controller->rirb_length = 256; controller->Write8(HDAC_RIRB_SIZE, RIRB_SIZE_256_ENTRIES); @@ -391,12 +388,13 @@ init_corb_rirb_pos(hda_controller* controller) } // Determine rirb offset in memory and total size of corb+alignment+rirb - rirbOffset = ALIGN(controller->corb_length * sizeof(corb_t), 128); - posOffset = ALIGN(rirbOffset + controller->rirb_length * sizeof(rirb_t), 128); - posSize = 8 * (controller->num_input_streams + uint32 rirbOffset = ALIGN(controller->corb_length * sizeof(corb_t), 128); + uint32 posOffset = ALIGN(rirbOffset + + controller->rirb_length * sizeof(rirb_t), 128); + uint8 posSize = 8 * (controller->num_input_streams + controller->num_output_streams + controller->num_bidir_streams); - memSize = PAGE_ALIGN(posOffset + posSize); + uint32 memSize = PAGE_ALIGN(posOffset + posSize); // Allocate memory area controller->corb_rirb_pos_area = create_area("hda corb/rirb/pos", @@ -408,9 +406,11 @@ init_corb_rirb_pos(hda_controller* controller) // Rirb is after corb+aligment controller->rirb = (rirb_t*)(((uint8*)controller->corb) + rirbOffset); - if ((rc = get_memory_map(controller->corb, memSize, &pe, 1)) != B_OK) { + physical_entry pe; + status_t status = get_memory_map(controller->corb, memSize, &pe, 1); + if (status != B_OK) { delete_area(controller->corb_rirb_pos_area); - return rc; + return status; } // Program CORB/RIRB for these locations @@ -463,10 +463,10 @@ init_corb_rirb_pos(hda_controller* controller) void hda_stream_delete(hda_stream* stream) { - if (stream->buffer_area >= B_OK) + if (stream->buffer_area >= 0) delete_area(stream->buffer_area); - if (stream->buffer_descriptors_area >= B_OK) + if (stream->buffer_descriptors_area >= 0) delete_area(stream->buffer_descriptors_area); free(stream); @@ -575,12 +575,12 @@ hda_stream_setup_buffers(hda_audio_group* audioGroup, hda_stream* stream, const char* desc) { // Clear previously allocated memory - if (stream->buffer_area >= B_OK) { + if (stream->buffer_area >= 0) { delete_area(stream->buffer_area); stream->buffer_area = B_ERROR; } - if (stream->buffer_descriptors_area >= B_OK) { + if (stream->buffer_descriptors_area >= 0) { delete_area(stream->buffer_descriptors_area); stream->buffer_descriptors_area = B_ERROR; } @@ -741,7 +741,7 @@ hda_stream_setup_buffers(hda_audio_group* audioGroup, hda_stream* stream, status_t hda_send_verbs(hda_codec* codec, corb_t* verbs, uint32* responses, uint32 count) { - hda_controller *controller = codec->controller; + hda_controller* controller = codec->controller; uint32 sent = 0; codec->response_count = 0; @@ -787,7 +787,7 @@ hda_verb_write(hda_codec* codec, uint32 nid, uint32 vid, uint16 payload) status_t -hda_verb_read(hda_codec* codec, uint32 nid, uint32 vid, uint32 *response) +hda_verb_read(hda_codec* codec, uint32 nid, uint32 vid, uint32* response) { corb_t verb = MAKE_VERB(codec->addr, nid, vid, 0); return hda_send_verbs(codec, &verb, response, 1); @@ -987,10 +987,8 @@ error: void hda_hw_stop(hda_controller* controller) { - int index; - // Stop all audio streams - for (index = 0; index < HDA_MAX_STREAMS; index++) { + for (uint32 index = 0; index < HDA_MAX_STREAMS; index++) { if (controller->streams[index] && controller->streams[index]->running) hda_stream_stop(controller, controller->streams[index]); } @@ -1001,8 +999,6 @@ hda_hw_stop(hda_controller* controller) void hda_hw_uninit(hda_controller* controller) { - uint32 index; - if (controller == NULL) return; @@ -1050,7 +1046,7 @@ hda_hw_uninit(hda_controller* controller) } // Now delete all codecs - for (index = 0; index < HDA_MAX_CODECS; index++) { + for (uint32 index = 0; index < HDA_MAX_CODECS; index++) { if (controller->codecs[index] != NULL) hda_codec_delete(controller->codecs[index]); } ############################################################################ Revision: hrev44668 Commit: a8b45a34711cd202f085a2acb22b151cb2019271 URL: http://cgit.haiku-os.org/haiku/commit/?id=a8b45a3 Author: Axel DÃrfler <axeld@xxxxxxxxxxxxxxxx> Date: Mon Oct 1 08:20:44 2012 UTC Added a test to compare various header parsers. * HaikuMailFormatFilter is using the new extract_from_header() method to retrieve its fields, but that one is often rather slow in comparison. * Added a test parse_fields() method that outperforms it considerably. ---------------------------------------------------------------------------- diff --git a/src/tests/kits/Jamfile b/src/tests/kits/Jamfile index 16ea224..d1739a8 100644 --- a/src/tests/kits/Jamfile +++ b/src/tests/kits/Jamfile @@ -5,6 +5,7 @@ SubInclude HAIKU_TOP src tests kits device ; SubInclude HAIKU_TOP src tests kits game ; SubInclude HAIKU_TOP src tests kits interface ; SubInclude HAIKU_TOP src tests kits locale ; +SubInclude HAIKU_TOP src tests kits mail ; SubInclude HAIKU_TOP src tests kits media ; SubInclude HAIKU_TOP src tests kits midi ; SubInclude HAIKU_TOP src tests kits net ; diff --git a/src/tests/kits/mail/Jamfile b/src/tests/kits/mail/Jamfile new file mode 100644 index 0000000..180cf89 --- /dev/null +++ b/src/tests/kits/mail/Jamfile @@ -0,0 +1,11 @@ +SubDir HAIKU_TOP src tests kits mail ; + +SetSubDirSupportedPlatformsBeOSCompatible ; + +UsePrivateHeaders mail shared ; + +SimpleTest header_test : + header_test.cpp + + : be $(TARGET_LIBSTDC++) $(TARGET_LIBSUPC++) mail +; diff --git a/src/tests/kits/mail/header_test.cpp b/src/tests/kits/mail/header_test.cpp new file mode 100644 index 0000000..5125cd2 --- /dev/null +++ b/src/tests/kits/mail/header_test.cpp @@ -0,0 +1,210 @@ +/* + * Copyright 2012, Axel DÃrfler, axeld@xxxxxxxxxxxxxxxxx + * Distributed under the terms of the MIT License. + */ + + +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <BufferIO.h> +#include <Directory.h> +#include <Entry.h> +#include <File.h> +#include <String.h> + +#include <mail_util.h> + + +struct mail_header_field { + const char* rfc_name; + const char* attr_name; + type_code attr_type; + // currently either B_STRING_TYPE and B_TIME_TYPE +}; + + +static const mail_header_field gDefaultFields[] = { + { "To", B_MAIL_ATTR_TO, B_STRING_TYPE }, + { "From", B_MAIL_ATTR_FROM, B_STRING_TYPE }, + { "Cc", B_MAIL_ATTR_CC, B_STRING_TYPE }, + { "Date", B_MAIL_ATTR_WHEN, B_TIME_TYPE }, + { "Delivery-Date", B_MAIL_ATTR_WHEN, B_TIME_TYPE }, + { "Reply-To", B_MAIL_ATTR_REPLY, B_STRING_TYPE }, + { "Subject", B_MAIL_ATTR_SUBJECT, B_STRING_TYPE }, + { "X-Priority", B_MAIL_ATTR_PRIORITY, B_STRING_TYPE }, + // Priorities with prefered + { "Priority", B_MAIL_ATTR_PRIORITY, B_STRING_TYPE }, + // one first - the numeric + { "X-Msmail-Priority", B_MAIL_ATTR_PRIORITY, B_STRING_TYPE }, + // one (has more levels). + { "Mime-Version", B_MAIL_ATTR_MIME, B_STRING_TYPE }, + { "STATUS", B_MAIL_ATTR_STATUS, B_STRING_TYPE }, + { "THREAD", B_MAIL_ATTR_THREAD, B_STRING_TYPE }, + { "NAME", B_MAIL_ATTR_NAME, B_STRING_TYPE }, + { NULL, NULL, 0 } +}; + + +enum mode { + PARSE_HEADER, + EXTRACT_FROM_HEADER, + PARSE_FIELDS +}; +static mode gParseMode = PARSE_HEADER; + + +void +format_filter(BFile& file) +{ + BMessage message; + + BString header; + off_t size; + if (file.GetSize(&size) == B_OK) { + if (size > 8192) + size = 8192; + char* buffer = header.LockBuffer(size); + file.Read(buffer, size); + header.UnlockBuffer(size); + } + + for (int i = 0; gDefaultFields[i].rfc_name; ++i) { + BString target; + if (extract_from_header(header, gDefaultFields[i].rfc_name, target) + == B_OK) + message.AddString(gDefaultFields[i].rfc_name, target); + } +} + + +status_t +parse_fields(BPositionIO& input, size_t maxSize) +{ + char* buffer = (char*)malloc(maxSize); + if (buffer == NULL) + return B_NO_MEMORY; + + BMessage header; + + ssize_t bytesRead = input.Read(buffer, maxSize); + for (int pos = 0; pos < bytesRead; pos++) { + const char* target = NULL; + int fieldIndex = 0; + int fieldStart = 0; + + // Test for fields we should retrieve + for (int i = 0; gDefaultFields[i].rfc_name; i++) { + size_t fieldLength = strlen(gDefaultFields[i].rfc_name); + if (!memcmp(&buffer[pos], gDefaultFields[i].rfc_name, + fieldLength) && buffer[pos + fieldLength] == ':') { + target = gDefaultFields[i].rfc_name; + pos += fieldLength + 1; + fieldStart = pos; + fieldIndex = i; + break; + } + } + + // Find end of line + while (pos < bytesRead && buffer[pos] != '\n') + pos++; + + // Fill in field + if (target != NULL) { + // Skip white space + while (isspace(buffer[fieldStart]) && fieldStart < pos) + fieldStart++; + + int end = pos - 1; + while (isspace(buffer[end]) && fieldStart < end - 1) + end--; + + char* start = &buffer[fieldStart]; + size_t sourceLength = end + 1 - fieldStart; + size_t length = rfc2047_to_utf8(&start, &sourceLength, + sourceLength); + start[length] = '\0'; + + header.AddString(gDefaultFields[fieldIndex].rfc_name, start); + target = NULL; + } + } + + free(buffer); + return B_OK; +} + + +void +process_file(const BEntry& entry) +{ + BFile file(&entry, B_READ_ONLY); + if (file.InitCheck() != B_OK) { + fprintf(stderr, "could not open file: %s\n", + strerror(file.InitCheck())); + return; + } + + switch (gParseMode) { + case PARSE_HEADER: + { + BBufferIO bufferIO(&file, 8192, false); + BMessage headers; + parse_header(headers, bufferIO); + break; + } + case EXTRACT_FROM_HEADER: + format_filter(file); + break; + case PARSE_FIELDS: + parse_fields(file, 8192); + break; + } +} + + +void +process_directory(const BEntry& directoryEntry) +{ + BDirectory directory(&directoryEntry); + BEntry entry; + while (directory.GetNextEntry(&entry, false) == B_OK) { + if (entry.IsDirectory()) + process_directory(entry); + else + process_file(entry); + } +} + + +int +main(int argc, char** argv) +{ + if (argc < 3) { + fprintf(stderr, "Expected: <parse|extract|fields> <path-to-mails>\n"); + return 1; + } + + if (!strcmp(argv[1], "parse")) + gParseMode = PARSE_HEADER; + else if (!strcmp(argv[1], "extract")) + gParseMode = EXTRACT_FROM_HEADER; + else if (!strcmp(argv[1], "fields")) + gParseMode = PARSE_FIELDS; + else { + fprintf(stderr, + "Invalid type. Must be one of parse, extract, or fields.\n"); + return 1; + } + + for (int i = 2; i < argc; i++) { + BEntry entry(argv[i]); + if (entry.IsDirectory()) + process_directory(entry); + else + process_file(entry); + } +}