// File: /workspace/github_c_makefile_star2_O2/miniupnp[P]hfsplustools/src/hfscommon.c
// Function: hfs_find_in_node
static
int hfs_find_in_node(unsigned char * catalog, unsigned char * p,
                     uint32_t parent_id, const char * name,
                     struct find_infos * infos)
{
	uint8_t kind;
#if 0
	uint32_t fLink, bLink;
	int height;
#endif
	uint16_t rec, num_records;
	uint32_t previous_node_number = 0;
	/* struct BTNodeDescriptor {
	 *  UInt32    fLink;	// next node
	 *  UInt32    bLink;	// previous node
	 *  SInt8     kind;
	 *  UInt8     height;
	 *  UInt16    numRecords;
	 *  UInt16    reserved;
	 * };
	 */
#if 0
	fLink = readu32(p);
	bLink = readu32(p+4);
	height = p[9];
#endif
	kind = p[8];
	num_records = readu16(p+10);
#if 0
	printf("Node %lu next=%u previous=%u kind=%d height=%d numRecords=%hu\n",
	       (unsigned long)(p - catalog) / catalog_node_size, fLink, bLink,
	       (int)kind, (int)height, num_records);
#endif
	p += 14;
	switch(kind) {
	case 0:	/* index */
		for(rec = 0; rec < num_records; rec++) {
			/* record */
			char str[256];
			uint16_t key_length = readu16(p);
			uint32_t cur_parent_id = readu32(p + 2);
			uint32_t node_number = readu32(p + key_length + 2);
			hfs_uni_to_str(str, sizeof(str), p + 6);
			/* Catalog file keys are compared first by parentID and
			 * then by nodeName. The parentID is compared as an
			 * unsigned 32-bit integer.
			 * For case-sensitive HFSX volumes, the characters in nodeName
			 * are compared as a sequence of unsigned 16-bit integers.
			 * For case-insensitive HFSX volumes and HFS Plus volumes,
			 * the nodeName must be compared in a case-insensitive way,
			 * as described in the Case-Insensitive String Comparison
			 * Algorithm section. */
			if(parent_id == cur_parent_id) {
				int comp = strcasecmp(str, name);
				/* https://developer.apple.com/library/archive/technotes/tn/tn1150.html#StringComparisonAlgorithm */
				if((name == NULL) || (0==comp)) {
					/* this one */
					p = catalog + node_number * catalog_node_size;
					return hfs_find_in_node(catalog, p, parent_id, name, infos);
				} else if(comp > 0) {
					/* previous one ! */
					p = catalog + previous_node_number * catalog_node_size;
					return hfs_find_in_node(catalog, p, parent_id, name, infos);
				}
			} else if(cur_parent_id > parent_id) {
				/* previous one ! */
				p = catalog + previous_node_number * catalog_node_size;
				return hfs_find_in_node(catalog, p, parent_id, name, infos);
			}
			p += key_length + 2 + 4;
			previous_node_number = node_number;
		}
		p = catalog + previous_node_number * catalog_node_size;
		return hfs_find_in_node(catalog, p, parent_id, name, infos);
	case 255:	/* LEAF */
		printf("LEAF %u records\n", num_records);
		for(rec = 0; rec < num_records; rec++) {
			char str[256];
			uint16_t record_type;
			uint16_t key_length = readu16(p);
			unsigned char * q;
			uint32_t valence;
			uint32_t folder_id;
			uint32_t cur_parent_id = readu32(p + 2);
			/* For file and folder records, this is the folder containing
			 * the file or folder represented by the record. For thread
			 * records, this is the CNID of the file or folder itself. */
			uint16_t HFSflags;
			char fileTypeCreator[9];
			int i;
			uint32_t block;
			hfs_uni_to_str(str, sizeof(str), p + 6);
			q = p + 2 + key_length;
			record_type = readu16(q);
			printf("%3d record type=%u parentId=%u \"%s\"",
			       rec, record_type, cur_parent_id, str);
			putchar('\n');
			//hexdump(q + 2, 32, 0);
			switch(record_type) {
			case 1: /* folder record */
				/* flags = readu16(q + 2); */
				valence = readu32(q + 4);
				folder_id = readu32(q + 8);
				HFSflags = readu16(q+56);
				//UInt32              createDate;
				//UInt32              contentModDate;
				//UInt32              attributeModDate;
				//UInt32              accessDate;
				//UInt32              backupDate;
				//HFSPlusBSDInfo      permissions;
				//FolderInfo          userInfo;
				//ExtendedFolderInfo  finderInfo;
				//UInt32              textEncoding;
				//UInt32              reserved;
				printf("    valence=%u folder_id=%u\n", valence, folder_id);
				printf("    folderinfo : (%u,%u)-(%u,%u) %04X",
					readu16(q+48), readu16(q+50),
					readu16(q+52), readu16(q+54),
					HFSflags);
				if(HFSflags & 0x0400) printf(" Custom Icon");
				if(HFSflags & 0x4000) printf(" Invisible");
				putchar('\n');
				if(cur_parent_id == parent_id &&
				   (name == NULL || 0 == strcasecmp(name, str))) {
					printf("FOUND FOLDER\n");
					infos->folder_id = folder_id;
					infos->p = q;
					return 1;
				}
				p = q + 88;
				break;
			case 2: /* file record */
				//file_id = readu32(q + 8);
				HFSflags = readu16(q+56);
				//UInt32              createDate;
				//UInt32              contentModDate;
				//UInt32              attributeModDate;
				//UInt32              accessDate;
				//UInt32              backupDate;
				//HFSPlusBSDInfo      permissions;
				//FileInfo            userInfo; // offset 48
				//ExtendedFileInfo    finderInfo;
				//UInt32              textEncoding;
				//UInt32              reserved2;
				//HFSPlusForkData     dataFork;  80 bytes
				//HFSPlusForkData     resourceFork; 80 bytes
				for(i=0; i<8; i++) {
					if(q[48+i] > ' ')
						fileTypeCreator[i] = q[48+i];
					else
						fileTypeCreator[i] = ' ';
				}
				fileTypeCreator[8] = '\0';
				printf("    fileinfo \"%s\" (%d,%d) %04X", fileTypeCreator, reads16(q+58), reads16(q+60), HFSflags);
				if(HFSflags & 0x0400) printf(" Custom Icon");
				if(HFSflags & 0x4000) printf(" Invisible");
				putchar('\n');
				printf("    dataFork size=%u blocks=%u extents:", readu32(q+88+4), readu32(q+88+12));
				for(i = 0; i < 8; i++) {
					block = readu32(q+88+16+i*8);
					printf(" (0x%06x, %u)", block, readu32(q+88+16+i*8+4));
					if(block == 0) break;
				}
				putchar('\n');
				printf("    resourceFork size=%u blocks=%u extents:", readu32(q+168+4), readu32(q+168+12));
				for(i = 0; i < 8; i++) {
					block = readu32(q+168+16+i*8);
					printf(" (0x%06x, %u)", block, readu32(q+168+16+i*8+4));
					if(block == 0) break;
				}
				putchar('\n');
				if(cur_parent_id == parent_id &&
				   (name == NULL || 0 == strcasecmp(name, str))) {
					printf("FOUND FILE\n");
					infos->p = q;
					return 1;
				}
				p = q + 248;
				break;
			case 3:	/* folder thread record */
			case 4:	/* file thread record */
				{
					uint16_t len;
					cur_parent_id = readu32(q + 4);
					len = readu16(q + 8);
					printf("parent_id=%u len=%u\n", cur_parent_id, len);
					p = q + 10 + len * 2;
				}
				break;
			default:
				printf("unknown\n");
				return 0;
			}
		}
		break;
	default:
		printf("unrecognized kind %u\n", kind);
	}
	return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x158, %rsp            # imm = 0x158
movq %r8, 0x28(%rsp)
movq %rcx, 0x18(%rsp)
movl %edx, 0xc(%rsp)
movq %rsi, %r12
movq %rdi, 0x10(%rsp)
leaq 0x50(%rsp), %r15
movzbl 0x8(%r12), %esi
movzbl 0xa(%r12), %ebx
shll $0x8, %ebx
leaq 0xe(%r12), %r13
movzbl 0xb(%r12), %eax
movzwl %ax, %eax
testl %esi, %esi
jne 0x23b0
orl %eax, %ebx
xorl %r12d, %r12d
subw $0x1, %bx
jb 0x234c
movq %r12, 0x20(%rsp)
movzwl (%r13), %eax
rolw $0x8, %ax
movzwl %ax, %ebp
leaq 0x2(%r13), %rdi
callq 0x188f
movl %eax, %r14d
leaq 0x2(,%rbp), %rdi
addq %r13, %rdi
callq 0x188f
movl %eax, %r12d
leaq 0x6(%r13), %rsi
movq %r15, %rdi
callq 0x2d7f
cmpl 0xc(%rsp), %r14d
jne 0x233c
movq %r15, %rdi
movq 0x18(%rsp), %r14
movq %r14, %rsi
callq 0x1050
testq %r14, %r14
je 0x2374
testl %eax, %eax
je 0x2374
jle 0x233e
jmp 0x235e
ja 0x235e
addq %rbp, %r13
addq $0x6, %r13
leaq 0x50(%rsp), %r15
jmp 0x22d6
imull 0x3d90(%rip), %r12d     # 0x60e4
addq 0x10(%rsp), %r12
jmp 0x22ac
movq 0x20(%rsp), %rsi
imull 0x3d7a(%rip), %esi      # 0x60e4
movq 0x10(%rsp), %rdi
addq %rdi, %rsi
jmp 0x2387
imull 0x3d68(%rip), %r12d     # 0x60e4
movq 0x10(%rsp), %rdi
addq %rdi, %r12
movq %r12, %rsi
movl 0xc(%rsp), %edx
movq 0x18(%rsp), %rcx
movq 0x28(%rsp), %r8
callq 0x2280
movl %eax, %ebx
movl %ebx, %eax
addq $0x158, %rsp            # imm = 0x158
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
cmpl $0xff, %esi
jne 0x27a4
orl %eax, %ebx
leaq 0x1592(%rip), %rdi      # 0x3957
movl %ebx, %esi
xorl %eax, %eax
callq 0x1090
leaq 0x50(%rsp), %r12
xorl %ecx, %ecx
movl %ebx, 0x40(%rsp)
cmpl %ebx, %ecx
je 0x27c5
movzbl (%r13), %eax
shll $0x8, %eax
movzbl 0x1(%r13), %edx
movl %ecx, 0x20(%rsp)
movq %rax, 0x38(%rsp)
movq %rdx, %r15
leaq (%rax,%rdx), %rbx
leaq 0x2(%r13), %rdi
callq 0x188f
movl %eax, %r14d
leaq 0x6(%r13), %rsi
movq %r12, %rdi
callq 0x2d7f
leaq (%rbx,%r13), %rbp
addq $0x2, %rbp
movzwl (%rbp), %eax
rolw $0x8, %ax
movq %r12, %rbx
movzwl %ax, %r12d
leaq 0x1534(%rip), %rdi      # 0x3968
movl 0x20(%rsp), %esi
movl %r12d, %edx
movl %r14d, 0x34(%rsp)
movl %r14d, %ecx
movq %rbx, %r8
xorl %eax, %eax
callq 0x1090
pushq $0xa
popq %rdi
callq 0x1040
leal -0x3(%r12), %eax
cmpl $0x2, %eax
jb 0x256d
movq %rbp, 0x10(%rsp)
cmpl $0x2, %r12d
je 0x25a8
cmpl $0x1, %r12d
jne 0x27b9
movq 0x10(%rsp), %r13
leaq 0x4(%r13), %rdi
callq 0x188f
movl %eax, %r14d
leaq 0x8(%r13), %rdi
callq 0x188f
movl %eax, %ebx
movzbl 0x38(%r13), %ebp
movl %ebp, %eax
shll $0x8, %eax
movzbl 0x39(%r13), %r12d
orl %eax, %r12d
leaq 0x14db(%rip), %rdi      # 0x398c
movl %r14d, %esi
movl %ebx, %edx
xorl %eax, %eax
callq 0x1090
movzwl 0x30(%r13), %eax
movzwl 0x32(%r13), %ecx
rolw $0x8, %ax
movzwl %ax, %esi
rolw $0x8, %cx
movzwl %cx, %edx
movzwl 0x34(%r13), %eax
rolw $0x8, %ax
movzwl %ax, %ecx
movzwl 0x36(%r13), %eax
rolw $0x8, %ax
movzwl %ax, %r8d
leaq 0x14b4(%rip), %rdi      # 0x39a9
movl %r12d, %r9d
xorl %eax, %eax
callq 0x1090
testb $0x4, %bpl
je 0x2513
leaq 0x14c3(%rip), %rdi      # 0x39cf
xorl %eax, %eax
callq 0x1090
testb $0x40, %bpl
je 0x2527
leaq 0x14bc(%rip), %rdi      # 0x39dc
xorl %eax, %eax
callq 0x1090
pushq $0xa
popq %rdi
callq 0x1040
movl 0x34(%rsp), %eax
cmpl 0xc(%rsp), %eax
leaq 0x50(%rsp), %r12
jne 0x255f
cmpq $0x0, 0x18(%rsp)
je 0x27cc
movq 0x18(%rsp), %rdi
movq %r12, %rsi
callq 0x1050
testl %eax, %eax
je 0x27cc
movq 0x10(%rsp), %r13
addq $0x58, %r13
jmp 0x2795
leaq 0x4(%rbp), %rdi
callq 0x188f
movzwl 0x8(%rbp), %ecx
rolw $0x8, %cx
movzwl %cx, %r14d
leaq 0x14df(%rip), %rdi      # 0x3a68
movl %eax, %esi
movl %r14d, %edx
xorl %eax, %eax
callq 0x1090
leaq 0xa(,%r14,2), %r13
addq %rbp, %r13
movq %rbx, %r12
jmp 0x2795
movq 0x10(%rsp), %rbx
movzbl 0x38(%rbx), %r12d
movzbl 0x39(%rbx), %eax
movq 0x38(%rsp), %rbp
addq %r15, %rbp
leaq 0x32(,%rbp), %rcx
addq %r13, %rcx
xorl %edx, %edx
pushq $0x20
popq %rdi
cmpq $0x8, %rdx
je 0x25e9
movzbl (%rcx,%rdx), %esi
cmpb $0x21, %sil
cmovbl %edi, %esi
movb %sil, 0x47(%rsp,%rdx)
incq %rdx
jmp 0x25ce
movl %r12d, %r8d
shll $0x8, %r8d
orl %eax, %r8d
movb $0x0, 0x4f(%rsp)
movzbl 0x3a(%rbx), %eax
shll $0x8, %eax
movzbl 0x3b(%rbx), %ecx
movswl %ax, %edx
orl %ecx, %edx
movzbl 0x3c(%rbx), %eax
shll $0x8, %eax
movzbl 0x3d(%rbx), %esi
movswl %ax, %ecx
orl %esi, %ecx
leaq 0x13c8(%rip), %rdi      # 0x39e7
leaq 0x47(%rsp), %rsi
xorl %eax, %eax
callq 0x1090
testb $0x4, %r12b
je 0x263f
leaq 0x1397(%rip), %rdi      # 0x39cf
xorl %eax, %eax
callq 0x1090
testb $0x40, %r12b
je 0x2653
leaq 0x1390(%rip), %rdi      # 0x39dc
xorl %eax, %eax
callq 0x1090
pushq $0xa
popq %rdi
callq 0x1040
leaq 0x5c(%rbx), %rdi
callq 0x188f
movl %eax, %r14d
leaq 0x64(%rbx), %rdi
callq 0x188f
leaq 0x138f(%rip), %rdi      # 0x3a06
movl %r14d, %esi
movl %eax, %edx
xorl %eax, %eax
callq 0x1090
movq %rbp, 0x38(%rsp)
leaq 0x6e(,%rbp), %r12
addq %r13, %r12
pushq $0x9
popq %rbp
decq %rbp
je 0x26d0
leaq 0x8(%r12), %rbx
leaq -0x4(%r12), %rdi
callq 0x188f
movl %eax, %r14d
movq %r12, %rdi
callq 0x188f
leaq 0x1372(%rip), %rdi      # 0x3a2e
movl %r14d, %esi
movl %eax, %edx
xorl %eax, %eax
callq 0x1090
movq %rbx, %r12
testl %r14d, %r14d
jne 0x2696
pushq $0xa
popq %rdi
callq 0x1040
movq 0x10(%rsp), %rbx
leaq 0xac(%rbx), %rdi
callq 0x188f
movl %eax, %r14d
leaq 0xb4(%rbx), %rdi
callq 0x188f
leaq 0x133d(%rip), %rdi      # 0x3a3c
movl %r14d, %esi
movl %eax, %edx
xorl %eax, %eax
callq 0x1090
movq 0x38(%rsp), %rax
leaq (%rax,%r13), %r12
addq $0xbe, %r12
pushq $0x9
popq %r13
decq %r13
je 0x2759
leaq 0x8(%r12), %rbx
leaq -0x4(%r12), %rdi
callq 0x188f
movl %eax, %r14d
movq %r12, %rdi
callq 0x188f
leaq 0x12e9(%rip), %rdi      # 0x3a2e
movl %r14d, %esi
movl %eax, %edx
xorl %eax, %eax
callq 0x1090
movq %rbx, %r12
testl %r14d, %r14d
jne 0x271f
pushq $0xa
popq %rdi
callq 0x1040
movl 0x34(%rsp), %eax
cmpl 0xc(%rsp), %eax
leaq 0x50(%rsp), %r12
jne 0x2789
cmpq $0x0, 0x18(%rsp)
je 0x27e2
movq 0x18(%rsp), %rdi
movq %r12, %rsi
callq 0x1050
testl %eax, %eax
je 0x27e2
movq 0x10(%rsp), %r13
addq $0xf8, %r13
movl 0x20(%rsp), %ecx
incl %ecx
movl 0x40(%rsp), %ebx
jmp 0x23d9
leaq 0x12d2(%rip), %rdi      # 0x3a7d
xorl %ebx, %ebx
xorl %eax, %eax
callq 0x1090
jmp 0x239c
leaq 0x1378(%rip), %rdi      # 0x3b38
callq 0x1060
xorl %ebx, %ebx
jmp 0x239c
leaq 0x1358(%rip), %rdi      # 0x3b2b
callq 0x1060
movq 0x28(%rsp), %rax
movl %ebx, 0x8(%rax)
jmp 0x27f3
leaq 0x1337(%rip), %rdi      # 0x3b20
callq 0x1060
movq 0x28(%rsp), %rax
movq 0x10(%rsp), %rcx
movq %rcx, (%rax)
pushq $0x1
popq %rbx
jmp 0x239c